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

Number-Character mapping in Haskell with list comprehension

我在 Haskell 中有一个简单的函数,它采用这样的元组列表:[(1,'a'),(2,'b')..(26,'z')] 和 returns 基于数字输入的字母值。所以理想情况下,

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 是一个接受整数的函数,returns 一个(短)字符列表。但是 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.

这是一个接受一个整数和 returns 一个字符列表的函数,所以我不确定我遗漏了什么。

您的问题是您正在使用 headlast,它们仅适用于列表,而您的 vector 是一个元组。您需要改用 fstsnd。或者更好的是,您可以使用模式匹配:

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

顺便说一句,[ x | x <- [1..26]][1..26] 相同,字符列表也类似。

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'