Reputation: 58
the task ist to translate this
f = do
c <- [1 .. 200]
b <- [1 .. 200]
guard (c >= b)
a <- [1 .. 200]
guard (a >= b && (c^2 - a^2 == b^2))
return (a,b, c)
into a non-sugar verion.
I think I got most of it figured out, but I'm stuck in the middle with a problem I need to fix before I can continue. So far I have:
f = [1 .. 200] >>= \c ->
[1 .. 200] >>= \b ->
if (c >= b)
then [1 .. 200] >>= \a -> if (a >= b && (c^2 - a^2 == b^2))
then return(a,b,c)
else return ()
else return ()
which does not compile. When I put in (a,b,c) for the return, it compiles, but obviously it does not give the expected result anymore. How do I return "nothing" in the else branches?
If I put in ((),(),()) as the return values, the compiler gets a "No instance for (Num [a]) arising from the literal '1'"
Upvotes: 1
Views: 349
Reputation: 183978
Instead of return ()
, which is [()]
, you must produce an empty list, so else []
or, with the generic guard
implementation else mzero
.
The success branch produces a list of triples, [(Int,Int,Int)]
(or Integer
, or another Num
type), so the failure branches must produce the same. Since failure means that no triple is found, they shall produce an empty list.
Note that in the []
monad, return x
is just [x]
and mzero
(from MonadPlus
) is the same as fail whatever
, namely []
.
Upvotes: 8
Reputation: 15278
guard
is not actually syntactic sugar. It's a function from Control.Monad
.
guard :: MonadPlus m => Bool -> m ()
guard True = return ()
guard False = mzero
In case of lists mzero
is []
. Read more here: http://en.wikibooks.org/wiki/Haskell/MonadPlus
Upvotes: 5