Javier M Mora jamarier at gmail.com
Thu Feb 17 20:13:08 CET 2011

```Hi, I'm trying to improve my skills with monads.

I'm started with project Euler problems but creating/using Monads.
I know that can be an overkill approach but, they are easy enough to

First Step: What I want?
------------------------

In this problem: I think monads as a DSL (Domain Specific Language)

main = do
print \$ sumM \$ do
makeList 10        -- create candidates list
multiples 3        -- choose multiples of 3
multiples 5        -- choose multiples of 5 (not choosed yet)

Data under de monad is a pair of lists:
(validValues, CandidatesNonValidYet)

so
makeList 10 = MyState ([],[1,2,3,4,5,6,7,8,9])

after
multiples 3 -> MyState ([3,6,9],[1,2,4,5,7,8])

after
multiples 5 -> MyState ([3,5,6,9],[1,2,4,7,8])

Second Step: What I have?
-------------------------

newType MyState a = MyState {execMyState :: ([a],[a])}

sumM :: (Integral a) => MyState a -> a
sumM = sum \$ fst \$ execMyState

makeList:: (Integral a) => a -> MyState a
makeList max = MyState ([],[1..max-1])
-- maybe: makeList max = return [1..max-1]

Third Step: function prototypes
-------------------------------

ideal:

multiple :: (Integral a) => a -> [a] -> MyState a

less ideal

multiple :: (Integral a) => a -> ([a],[a]) -> MyState a

------------------------------

return = error "no implemented"
--(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
m >>= k = let (v, c) = execMyState m
n      = k c
(nv, nc) = execMyState n
in MyState (v++nv, nc)

with this instanciation: k :: a -> m b
but (multiple 3) :: [a] -> MyState a

in one the function ask for a value "a" type and in the other case for a
list. So, doesn't compile :-(

Second option:

newType MyState a = MyState {execMyState :: (a,a)}

I like more the other option, because when you say "MyState Int" or
"MyState float" you're saying than the possibilities are type Int or
float or whatever. With this option (the second) you have to coerce that
a type have to be a container in other part.

if I can force (MonadPlus a) :

return a = MyState (a,mzero)
--(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
m >>= k = let (v, c) = execMyState m
n      = k c
(nv, nc) = execMyState n
in MyState (v `mplus` nv, nc)

or maybe I must use Monoid... but I don't know how force that
and here I'm stuck

Any hints?

```