getArgs 字符串转int

getArgs string to int

我正在尝试在 haskell 中编写我的第一个 IO 程序,但我似乎无法从命令行 运行 我想要命令 cabal 运行 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))

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

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

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


Second,你的函数 toBin returns 是 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