问题描述
我正在尝试在haskell中编写我的第一个IO程序,但似乎无法从命令行运行它 我希望命令cabal run 5> result.txt在result.txt中以二进制形式打印5。我找到了一些转换代码,但是在实现它时出现错误:
src/Main.lhs:23:28: error:
• Couldn't match type ‘Int’ with ‘Char’
Expected type: String
Actual type: [Int]
• In the second argument of ‘writeFile’,namely ‘(toBin (args))’
In a stmt of a 'do' block: writeFile "file.txt" (toBin (args))
In the expression:
do { args <- getArgs;
writeFile "file.txt" (toBin (args)) }
src/Main.lhs:23:34: error:
• Couldn't match expected type ‘Int’ with actual type ‘[String]’
• In the first argument of ‘toBin’,namely ‘(args)’
In the second argument of ‘writeFile’,namely ‘(toBin (args))’
In a stmt of a 'do' block: writeFile "file.txt" (toBin (args))
这是我的代码:
module Main where
import System.Environment
import Data.List
import Data.Maybe
import qualified Data.Map as M (Map,empty,insert,lookup)
import Data.Char (ord)
toBin:: Int -> [Int]
toBin 0 = [0]
toBin n = reverse (helper n)
helper:: Int -> [Int]
helper 0 = []
helper n = let (q,r) = n `divMod` 2 in r : helper q
main :: IO ()
main = do
args <- getArgs
writeFile "file.txt" (toBin(args))
解决方法
首先,您的函数toBin
需要一个Int
参数,但是args
的类型为[String]
-即字符串列表。因此,您需要(从您的描述中)获取第一个参数并将其转换为Int
。最便宜,最肮脏的方法是先head
,然后再read
转换为Int
:
writeFile "file.txt" (toBin . read . head $ args)
但是请注意,如果(1)参数列表为空(即没有“第一个”元素)或(2)第一个参数不是数字,则此代码将在运行时崩溃。如果您不喜欢崩溃,请考虑使用更安全的替代方法,例如headMay
或reads
。
第二,您的函数toBin
返回一个Int
的列表,但是writeFile
需要一个String
类型的参数。最便宜,最脏的转换方式是通过show
:
writeFile "file.txt" (show . toBin . read . head $ args)
但是,列表的show
实现将产生一个看起来不像二进制数字的字符串。看起来像"[0,1,1]"
。如果您对此表示不满意,则必须编写自己的函数将列表转换为看起来像二进制数字的字符串。最便宜,最肮脏的方法是将show
应用于列表的每个元素,然后将结果字符串粘合在一起:
binToStr :: [Int] -> String
binToStr = concat . map show
...
writeFile "file.txt" (binToStr . toBin . read . head $ args)
或者可以简化为concatMap
:
binToStr = concatMap show