这个列表理解代码有什么问题?

时间:2012-03-26 22:20:09

标签: haskell

我的目标是列出数组a的所有元素,其值大于其索引位置。我写了一个像这样的Haskell代码。

[a|i<-[0..2],a<-[1..3],a!!i>i]

在ghci prelude提示符上测试时,我收到以下错误消息,我无法理解。

No instance for (Num [a]) arising from the literal 3 at <interactive>:1:20 Possible fix: add an instance declaration for (Num [a])

2 个答案:

答案 0 :(得分:10)

给定表达式a!!i,Haskell将推断a是一个列表(即a::[a])。给定a<-[1..3]表达式,Haskell将推断a将具有类型Num a => a(因为您从a值列表中绘制Num a => a。为了统一这些类型,Haskell得出结论:a实际上必须是Num a => [a]类型。

最重要的是,将a视为一个上下文中的列表并将其作为另一个上下文中的数字列表中的元素是没有意义的。

修改

我想你可以用这样的东西做你想做的事:

f xs = map fst . filter (uncurry (>)) $ (xs `zip` [0..])

表达式xs `zip` [0..]创建一对对列表,其中每对中的第一个值来自xs,第二个值来自[0..](从0开始的无限列表)。这用于将索引与xs中的每个值相关联。表达式uncurry (>)<运算符转换为对的函数。因此,表达式filter (uncurry (>))仅将对列表过滤为第一个值大于第二个值的元素。最后,map fstfst函数应用于每对值,并将结果作为列表返回(fst函数返回一对的第一个值。)

编辑2

编写无意义的代码很有趣,所以我给你:

f = map snd . filter (uncurry (<)) . zip [0..]

答案 1 :(得分:1)

import Data.Maybe
import Control.Monad

f = catMaybes . zipWith (mfilter.(<)) [0..] . map Just

免责声明:给定的代码不是证据阅读,可能是在清醒之外做出的。作者几乎没有回忆它的内容。