我在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列表,所以我不确定我错过了什么。
答案 0 :(得分:3)
您的问题是,您使用的head
和last
仅适用于列表,而您的vector
是元组。您需要使用fst
和snd
代替。或者甚至更好,你可以使用模式匹配:
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'