Haskell模式匹配列表的字符到Ints

时间:2017-12-11 03:42:53

标签: haskell

我对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]]

3 个答案:

答案 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))