将getArgs字符串转换为int

时间:2020-08-18 03:29:08

标签: haskell args

我正在尝试在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))

1 个答案:

答案 0 :(得分:5)

首先,您的函数toBin需要一个Int参数,但是args的类型为[String]-即字符串列表。因此,您需要(从您的描述中)获取第一个参数并将其转换为Int。最便宜,最肮脏的方法是先head,然后再read转换为Int

writeFile "file.txt" (toBin . read . head $ args)

但是请注意,如果(1)参数列表为空(即没有“第一个”元素)或(2)第一个参数不是数字,则此代码将在运行时崩溃。如果您不喜欢崩溃,请考虑使用更安全的替代方法,例如headMayreads


第二,您的函数toBin返回一个Int的列表,但是writeFile需要一个String类型的参数。最便宜,最脏的转换方式是通过show

writeFile "file.txt" (show . toBin . read . head $ args)

但是,列表的show实现将产生一个看起来不像二进制数字的字符串。看起来像"[0, 1, 1, 0, 1]"。如果您对此表示不满意,则必须编写自己的函数将列表转换为看起来像二进制数字的字符串。最便宜,最肮脏的方法是将show应用于列表的每个元素,然后将结果字符串粘合在一起:

binToStr :: [Int] -> String
binToStr = concat . map show

...

writeFile "file.txt" (binToStr . toBin . read . head $ args)

或者可以简化为concatMap

binToStr = concatMap show