Haskell模式匹配字符到整数的列表

Haskell模式匹配字符到整数的列表,haskell,Haskell,我对哈斯克尔是个新手。我想把字符列表转换成整数 假设我有一张单子 example = ["3..25.4"] 我想将此列表转换为以下格式的整数: [Just 3, Nothing, Nothing, Just 2, Just 5, Just 4] 其中一个句号(.)被替换为Nothing,n被替换为Just n 这是我目前的代码: yb :: [[Char]] -> [Maybe Int] yb [[]] = [] yb (x:xs) = if x == '.' then Nothin

我对哈斯克尔是个新手。我想把字符列表转换成整数

假设我有一张单子

example = ["3..25.4"]
我想将此列表转换为以下格式的整数:

[Just 3, Nothing, Nothing, Just 2, Just 5, Just 4]
其中一个句号(.)被替换为Nothing,n被替换为Just n

这是我目前的代码:

yb :: [[Char]] -> [Maybe Int]
yb [[]] = []
yb (x:xs) = if x == '.' then Nothing:yb(xs) else Just x:yb(xs)
不完全确定下一步该怎么做/出了什么问题,尽管我知道即使我的代码正常运行,顺序也会颠倒,所以这是另一个问题

无论如何,我在执行代码时遇到的错误是:

Couldn't match the type '[Char]' with 'Int'
Expected type: [Maybe Int]    Actual type: [Maybe [Char]]
无论如何,我在执行代码时遇到的错误是:

Couldn't match the type '[Char]' with 'Int'
Expected type: [Maybe Int]    Actual type: [Maybe [Char]]
无法将类型“[Char]”与预期的类型“[Int]”匹配:[可能是Int] 实际类型:[可能是[Char]]

这是一个类型错误,来自编译器(特别是来自类型检查器)。这会在编译过程的早期运行,即在执行之前运行

第一个问题是我认为你不确定你的输入应该是什么。您可以按以下方式提供示例输入:

示例=[“3..25.4”]

这是一个包含单个字符串元素的列表,其类型为
[string]
(或者等效为
[[Char]]]
,因为
string
[Char]
的同义词)。在我看来,您可能希望
yb
的类型为:

yb::[Char]->[Maybe Int]

并获取输入,如
“3..25.4”::[Char]

我想你可以从这里解决这个问题。如果你在理解你将遇到的类型错误方面有困难,谷歌或其他一些问题会对你有所帮助

最后一件事:您正在以
C
传统的风格编写函数调用,但在haskell中它们不是这样工作的;你应该只写
yb-xs
而不是
yb(xs)
。同样,如果一个函数得到三个参数,它的调用类似于
fxyz

所有这些都是等效的:

yb xs
yb(xs)
yb (xs)
yb ((xs)) -- all of these parens are redundant
yb x y z
(yb x) y z
(yb x y) z
((yb x ) y ) z
同样有趣的是,如果
yb
接受三个参数,那么所有这些参数都是等效的:

yb xs
yb(xs)
yb (xs)
yb ((xs)) -- all of these parens are redundant
yb x y z
(yb x) y z
(yb x y) z
((yb x ) y ) z

代码的优点在于它在
map
的驾驶室中工作,即:

input  :: [a]
output :: [b] -- where each b matches an a
请记住,
map::(a->b)->[a]->[b]
,因此您只需编写一个函数
a->b
,在本例中是
[Char]->[Maybe Int]
。等等--这不是
[a]->[b]
的另一个实例吗

map . map :: (a -> b) -> [[a]] -> [[b]]
本例中的函数是
Char->Maybe Int

import Data.Char (digitToInt)

f :: Char -> Maybe Int
f '.' = Nothing
f x   = Just . digitToInt $ x
(或者您可以自己实现
digitToInt


然后,您的代码运行
[[Char]]->可能是Int
,例如
,因为列表的类型是
[[Char]]
,当模式匹配
(x:xs)
时,您会查看列表中的每个
[Char]
,而不是每个
Char
。因此,当您检查
x==“
”时,您要检查的是
“==”3..25.4“
,这不是您想要的

此外,如果您正在构造一个
[Maybe Int]
列表,则需要先将字符串转换为整数,然后再应用
Just x
。否则,您将只应用Char
,这不是正确的数据类型。这可以从中完成

我建议创建一个函数,将
[Char]
转换为
[Maybe Int]

import Data.Char

one_string :: [Char] -> [Maybe Int]
one_string [] = []
one_string (x:xs) 
    | x == '.' = Nothing : one_string xs
    | otherwise = Just (digitToInt x) : one_string xs
其工作原理如下:

*Main> one_string "3..25.4"
[Just 3,Nothing,Nothing,Just 2,Just 5,Nothing,Just 4]
然后,您可以对列表中的每个
[Char]
应用此函数:

yb :: [[Char]] -> [[Maybe Int]]
yb [] = []
yb (x:xs) = one_string x : yb xs
哪些产出:

*Main> yb ["3..25.4", "43..32"]
[[Just 3,Nothing,Nothing,Just 2,Just 5,Nothing,Just 4],[Just 4,Just 3,Nothing,Nothing,Just 3,Just 2]]
注意:这里唯一的区别是它返回一个
[[Maybe Int]]
数据类型,如果列表中有多个字符串,这是有意义的。我还尽可能地简化了上面的代码,正如其他答案所示,它们是可以使用的高阶函数

编辑:

您还可以使用:

或者更简洁一些:

yb :: [[Char]] -> [[Maybe Int]]
yb = (map . map) (\x -> if x == '.' then Nothing else Just (digitToInt x))

我认为这个例子应该是
…,只有2个,只有5个,没有,只有4个。