Haskell如何读取用户输入传入toDigits函数拆分7位数字为整数列表
Haskell实现用户输入数字拆分为单个数字列表
需求说明
实现逻辑提示用户输入7位数字,将输入数字转换为单个整数组成的列表,预期运行效果:
toDigits 1234567 = [1, 2, 3, 4, 5, 6, 7] toDigitsReverse 1234567 = [7, 6, 5, 4, 3, 2, 1]
注意:示例中的1234567需由用户动态输入,不可硬编码。
现存问题
已分别实现数字拆分逻辑和输入输出框架,但无法将两部分逻辑结合,初始硬编码版本代码如下:
toDigits :: Integral x => x -> [x] toDigits 0 = [] toDigits x = toDigits (x div 10) ++ [x mod 10] main :: IO () main = do putStr "The split array is " print(toDigits 1234567)
尝试接入用户输入的版本运行时报错,代码如下:
toDigits :: Integer -> [Int] toDigits n = map (\x -> read [x] :: Int) (show n) main :: IO () main = do putStrLn "Please enter the USI number: " usi <- getLine let usiasnumber = read usi :: Int print("The USI split into single digit array is " ++ toDigits usiasnumber)
运行返回错误:
Couldn't match type ‘Int’ with ‘Char’ Expected type: [Char] Actual type: [Int]
错误原因
- 核心类型错误:Haskell中
++运算符要求两侧列表的元素类型完全一致,拼接逻辑左侧的提示文本是String类型(即[Char]),右侧toDigits返回值是[Int]类型,两类列表无法直接拼接。 - 初始版本语法错误:
div、mod作为中缀运算符使用时,必须用反引号包裹,正确写法为x `div` 10、x `mod` 10,直接写x div 10会被编译器识别为未定义的普通标识符。
修正后可运行代码
-- 正序拆分数字为单个整数列表 toDigits :: Integral x => x -> [x] toDigits 0 = [] toDigits x = toDigits (x `div` 10) ++ [x `mod` 10] -- 逆序拆分直接复用正序逻辑反转结果即可 toDigitsReverse :: Integral x => x -> [x] toDigitsReverse = reverse . toDigits main :: IO () main = do putStr "Please enter 7 digits: " -- 直接读取整数类型输入,无需手动getLine后转类型 input <- readLn :: IO Int -- 非字符串值拼接前需用show转为字符串 putStrLn $ "The split array is " ++ show (toDigits input) putStrLn $ "The reversed split array is " ++ show (toDigitsReverse input)
补充说明
- 若需要严格校验输入为7位数字,可在读取输入后判断数值是否在1000000~9999999区间内,不符合要求则提示用户重新输入。
readLn可以直接读取指定类型的IO输入,比getLine后手动调用read的写法更简洁。- 所有非字符串类型的值要和字符串拼接时,必须先通过
show方法转为对应字符串表示。
内容的提问来源于stack exchange,提问作者Justin Thomas
相关产品推荐
相关产品推荐

