This has to be dead simple and I'm unhappy I can't figure it out at this point in my Haskell experience. I want a cartesian product of a list with itself, but I want to filter out identical items. I don't want a post filter.
This gets me the CP - seemingly set up to simply add a filter...
p as bs = do
a <- as
b <- bs
return (a,b)
p [1,2,3] [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
I have read that return ()
is basically a noop in do notation - but this doesn't compile. (Are the tuples being mixed up)
pf as bs = do
a <- as
b <- bs
if a == b then return () else return (a,b)
* Couldn't match type `()' with `(a, a)'
Expected type: [(a, a)]
Actual type: [()]
I have tried a few other things, like the if'
function from the Haskell wiki. I also tried when
without success. When the filter is when
when (a /= b) return (a,b)
* Couldn't match type `m0 (a, a)' with `()'
Expected type: (a, a) -> ()
Actual type: (a, a) -> m0 (a, a)
I suppose these error messages are leading me by the nose to the issue but I am not adept at translating most of them yet.
There is very possibly a higher level function that might handle this in a more straight forward way (filterM ?), and I'll be happy to hear about its usage, but I still want to know how to solve this issue in the pf
function above.
Thanks
Try:
main = print $ p [1,2,3] [1,2,3] -- [(1,2),(1,3),(2,1),(2,3),(3,1),(3,2)]
p as bs =
do
a <- as
b <- bs
if a == b then [] else return (a, b)
I've learned Haskell a bit only recently, so I may be wrong. In this context, return (a, b)
is nothing more than the expression [(a, b)]
(which is natural, since for monad []
you need a function with the output of type [t]
). So you need to provide the same type, i.e., the empty list []
.
On the other hand when you write return ()
it actually is [()]
, whose type is [()]
, which is not the same as, say, the type [(Int, Int)]
.