Contact/support | Changelog

When Monads go bad

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import Control.Monad

newtype BadMonad a = BadMonad ([Int] -> a)

runBadMonad :: BadMonad a -> a
runBadMonad (BadMonad m) = m [0..]

unique :: BadMonad Int
unique = BadMonad head

split :: [a] -> ([a],[a])
split (x1:x2:xs) = (x1:xs1, x2:xs2)
  where (xs1,xs2) = split xs

instance Monad BadMonad where
  return x = BadMonad (const x)
  BadMonad m >>= f = BadMonad $ \xs ->
                     let (xs1,xs2)  = split xs
                         BadMonad n = f (m xs1)
                     in n xs2

-- By the monad laws all of these should return the same result

demo1 = runBadMonad $
  do (x1,x2) <- do y1 <- unique
                   y2 <- unique
                   return (y1,y2)
     x3      <- unique
     return (x1,x2,x3)
-- (0,2,1)

-- We rely on these laws to make it OK to substitute in combinators
demo1a = runBadMonad $
  do (x1,x2) <- liftM2 (,) unique unique
     x3      <- unique
     return (x1,x2,x3)
-- (0,2,1)

demo2 = runBadMonad $
  do x1 <- unique
     x2 <- unique
     x3 <- unique
     return (x1,x2,x3)
-- (0,1,3)

demo3 = runBadMonad $
  do x1 <- unique
     x2 <- unique
     return ()
     x3 <- unique
     return (x1,x2,x3)
-- (0,1,7)