我对Haskell相当新鲜。我希望将Chars列表转换为Maybe Ints
假设我有一个列表
example = ["3..25.4"]
我希望以下列格式将此列表转换为Maybe Ints:
[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]]
答案 0 :(得分:3)
无论如何,我执行代码时得到的错误是:
无法匹配' [Char]'与' Int'预期类型:[也许Int] 实际类型:[可能[Char]]
这是来自编译器(特别是来自类型检查器)的类型错误。这在编译过程的早期运行,即在执行之前运行。
第一个问题是我认为您不确定您的输入应该是什么。您将示例输入提供为:
example = [" 3..25.4"]
这是单个字符串元素的列表,它的类型为[String]
(或等效[[Char]]
,因为String
是{{的同义词1}})。在我看来,您可能希望[Char]
的类型为:
yb :: [Char] - > [也许Int]
并接受yb
我想你能够从这里解决它。如果您无法理解所获得的类型错误,那么谷歌或其他SO问题可能会有所帮助。
最后一件事:你正在以"3..25.4" :: [Char]
传统的方式编写函数调用,但这并不是它们在haskell中的工作方式;你应该只写C
而不是yb xs
。同样,如果一个函数得到三个参数,它就像yb(xs)
一样被调用。
所有这些都是等价的:
f x y z
同样有趣的是,如果yb xs
yb(xs)
yb (xs)
yb ((xs)) -- all of these parens are redundant
有三个参数,那么所有这些都是等价的:
yb
答案 1 :(得分:2)
您的代码的好处在于它在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]] -> Maybe Int
,即(map . map) f example
答案 2 :(得分:1)
由于您的列表类型为[[Char]]
,因此当您模拟匹配(x:xs)
时,您会查看列表中的每个[Char]
,而不是每个Char
。因此,当您检查x == "."
时,检查是否"." == "3..25.4"
,这不是您想要的。
此外,如果您构建[Maybe Int]
列表,则需要先将字符串转换为整数,然后再应用Just x
。否则,您将应用Just Char
,这不是正确的数据类型。可以使用digitToInt
中的Data.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]]
数据类型,如果您的列表中有多个字符串,这是有意义的。我还保持上面的代码尽可能简单,它们是你可以使用的高阶函数,正如其他答案所示。
修改强>
您也可以使用map
:
yb :: [[Char]] -> [[Maybe Int]]
yb lst = map one_string lst
where one_string [] = []
one_string (x:xs)
| x == '.' = Nothing : one_string xs
| otherwise = Just (digitToInt x) : one_string xs
或更简洁的内容:
yb :: [[Char]] -> [[Maybe Int]]
yb = (map . map) (\x -> if x == '.' then Nothing else Just (digitToInt x))