suresh
suresh

Reputation: 1109

What is wrong with this list comprehension code?

My aim is to list all elements of the array a whose values are greater than their index positions. I wrote a Haskell code like this.

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

When tested on ghci prelude prompt, I get the following error message which I am unable to understand.

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

Upvotes: 3

Views: 414

Answers (2)

Landei
Landei

Reputation: 54574

import Data.Maybe
import Control.Monad

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

Disclaimer: The given code was not proof read and may have been made outside of sobriety. The author has little recollection of what it is about.

Upvotes: 1

Daniel Pratt
Daniel Pratt

Reputation: 12077

Given the expression a!!i, Haskell will infer that a is a list (i.e. a::[a]). Given the expression a<-[1..3], Haskell will infer that a will have type Num a => a (because you are drawing a from a list of Num a => a values). Trying to unify these types, Haskell concludes that a must actually be of type Num a => [a].

The bottom line is that it doesn't make sense to treat a as a list in one context and as an element from a list of numbers in another context.

EDIT

I'm thinking you could do what you want with something like this:

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

The expression xs `zip` [0..] creates a list of pairs, where the first value in each pair is drawn from xs and the second value from [0..] (an infinite list starting from 0). This serves to associate an index to each value in xs. The expression uncurry (>) converts the < operator into a function that works on pairs. So the expression filter (uncurry (>)) filters a list of pairs to only those elements where the first value is greater than the second. Finally, map fst applies the fst function to each pair of values and returns the result as a list (the fst function returns the first value of a pair).

EDIT 2

Writing pointless code is fun, and so I give you:

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

Upvotes: 10

Related Questions