[Haskell-beginners] Monads...

nanothief nanothief at gmail.com
Wed Jan 28 22:38:38 EST 2009


Cory Knapp wrote:
> Hello, so, I'm having a simple problem with monads: I have no idea how 
> to actually use them. I understand the category theory (or, at least 
> well enough to be able to explain "what is a monad"); I understand the 
> way to declare something as a monad instance, but I just don't get how 
> to program with them. Can anyone provide me with, or direct me 
> towards, some simple monads and some ways of using (for example) the 
> monadic properties of lists?
>
> Thanks,
> Cory
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
I found that http://www.haskell.org/all_about_monads/html/index.html 
gave a lot of nice examples of using list and maybe monads. The list 
monad is particularly useful for finding possible solutions given 
available input values.
For example, with the problem
x + 8y = 114
3x - 8y + 4z = 182
x < y < z < 100
Find solutions for x,y,z

The program:
res :: [(Int,Int,Int)]
res = do
  x <- [1..100]
  y <- [1..100]
  z <- [1..100]
  guard $ x + 8 * y == 114
  guard $ 3*x - 8*y + 4*z == 182
  guard $ x < y
  guard $ y < z
  return (x,y,z)

will output all the possible solutions. Note how close the program is to 
the actual problem. The values of x,y, and z are chosen from the value 
[1..100], but if a guard statement fails, the (x,y,z) choice is abandoned.

Another example (taken from 
http://www.mathsisfun.com/puzzles/sum-of-digits-is-43-solution.html )
*The Puzzle:* I am thinking of a 6-digit number. The sum of the digits 
is 43.

And only two of the following three statements about the number are true:

(1) it's a square number,
(2) it's a cube number, and
(3) the number is under 500000.

the program
answer = do
  d1 <- [0..9]
  d2 <- [0..9]
  d3 <- [0..9]
  d4 <- [0..9]
  d5 <- [0..9]
  d6 <- [0..9]
  let digitSum = d1 + d2 + d3 + d4 + d5 + d6
  let value = d1 + d2*10 + d3*100 + d4*1000 + d5*10000 + d6*100000
  guard $ digitSum == 43
  let lessThan500000 = digitSum < 500000
  let isSquare = (round $ sqrt (fromIntegral value)) ^ 2 == value
  let isCube = (round $ (fromIntegral value) ** (1/3)) ^ 3 == value
  guard $ length (filter id [lessThan500000,isSquare,isCube]) == 2
  return value

will output the three answers (not that the author only found one 
solution!).
 




More information about the Beginners mailing list