Haskell中的数字字符映射与列表理解

时间:2015-01-13 05:05:19

标签: haskell

我在Haskell中有一个简单的函数,它接受这样的元组列表:[(1,'a'),(2,'b')..(26,'z')],并根据输入的数字返回一个字母值。理想情况下,

getCharByNum 3
> "c"

我正在尝试使用列表推导,并过滤掉每个不包含该数字的元组。

zippedChars = zip [ x | x <- [1..26]]  [ x | x <- ['a'..'z']]
getCharByNum :: (Integral a) => a -> [Char]
getCharByNum num = [ head vector | vector <- zippedChars, num == last vector ]

我认为这是有道理的... getCharByNum是一个接受整数的函数,并返回一个(简短的)Chars列表。但是GHCI抛出了这个错误:

Couldn't match expected type `[a]'
            with actual type `(Integer, Char)'
In the first argument of `last', namely `vector'
In the second argument of `(==)', namely `last vector'
In the expression: num == last vector

如何正确构建允许此功能运行的类型签名? (我知道这可以通过索引轻松完成,或者甚至更容易使用Data.Char.ord,但我试图更好地理解列表推导)

编辑:我已经清理了一下代码:

zippedChars = zip [1..26] ['a'..'z']
getCharByNum :: Integral -> [Char]
getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]

但我仍然收到此错误:

folds.hs:50:18:
    Expecting one more argument to `Integral'
    In the type signature for `getCharByNum':
      getCharByNum :: (Integral) -> [Char]
Failed, modules loaded: none.

这是一个函数,它接受一个整数并返回一个Chars列表,所以我不确定我错过了什么。

2 个答案:

答案 0 :(得分:3)

您的问题是,您使用的headlast仅适用于列表,而您的vector是元组。您需要使用fstsnd代替。或者甚至更好,你可以使用模式匹配:

getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]

顺便说一下,[ x | x <- [1..26]][1..26]相同,对于字符列表也是如此。

答案 1 :(得分:1)

Integral是一个类型类。积分不是一种类型。 a是Integral的一个实例,所以我们在签名的开头声明它。

zippedChars :: Integral a => [(a, Char)]
zippedChars = zip [1..26] ['a'..'z']

getCharByNum :: Integral a => a -> String
getCharByNum num = [ c | (n,c) <- zippedChars, num == n ]

>>> getCharByNum 3
'c'

建议:

>>> ['a'..'z'] !! 4
'c'