Page 1 of 1

## 6 Replies - 1425 Views - Last Post: 12 November 2014 - 07:56 AM

### #1 cfoley

• Cabbage

Reputation: 2391
• Posts: 5,023
• Joined: 11-December 07

Posted 11 November 2014 - 10:00 AM

I'm being introduced to Haskell monads by the book Seven Languages in Seven Weeks. It uses an example of a monad that models a drunken pirate making a treasure map. Here it is:

```module Main where
data Position t = Position t deriving (Show)

stagger (Position d) = Position (d + 2)
crawl (Position d) = Position (d + 1)

rtn x = x
x >>== f = f x

treasureMap pos = pos >>==
stagger >>==
stagger >>==
crawl >>==
rtn

```

The function treasureMap uses the monad without syntactic sugar. I think I understand it, and it's a lot less magical than I was expecting. >>== is an operator that lets me pipe functions together via currying. (Please correct me if I am wrong.)

Next the book explains there is the "do" notation that adds syntactic sugar to monads, and it gives an example using IO. This doesn't satisfy me because I can't see how the sugar relates to the core syntax. To help me get to the bottom of it, I'm trying to rewrite the treadureMap function to use the "do" syntax. This is the best I have come up with.

```	treasureMap2 pos = do
let { x = stagger pos } ;
let { y = stagger x } ;
let { z = crawl y } ;
rtn z

```

This seems considerably worse than the first incarnation. In fact, it is considerably worse than the equivalent monad-free implementation:

```	treasureMap3 pos = let x = stagger pos
y = stagger x
z = crawl y
in z
```

Any help or advice would be very much appreciated.

Is This A Good Question/Topic? 0

### #2 sepp2k

• D.I.C Lover

Reputation: 2740
• Posts: 4,392
• Joined: 21-June 11

Posted 11 November 2014 - 04:48 PM

cfoley, on 11 November 2014 - 06:00 PM, said:

The function treasureMap uses the monad without syntactic sugar. I think I understand it, and it's a lot less magical than I was expecting. >>== is an operator that lets me pipe functions together via currying. (Please correct me if I am wrong.)

There is no currying going on here - all functions involved are unary. But you're right that it's piping functions.

Quote

```	treasureMap2 pos = do
let { x = stagger pos } ;
let { y = stagger x } ;
let { z = crawl y } ;
rtn z

```

The rules of do notation are as follows:

```do {e}                   = e
do {e;stmts}             = e >> do {stmts}
do {p <- e; stmts}       = let ok p = do {stmts}
ok _ = fail "..."
in e >>= ok
do {let decls; stmts}    = let decls in do {stmts}

```

As you can tell the shortened syntax for lets does not involve any monad operations - it is just a syntactic convenience (due to the fact that a do-block is, well, a block making the in redundant as it can be inferred from the indentation). So the only thing about your above code that's related to monads is your use of rtn/return, which isn't related to do notation.

If you want a do-block that corresponds to your use of >>=, you'll need to use the <- operator in the block like this:

```do
x <- pos
y <- stagger p
z <- stagger p2
zz <- crawl
return zz

```

### #3 cfoley

• Cabbage

Reputation: 2391
• Posts: 5,023
• Joined: 11-December 07

Posted 11 November 2014 - 05:33 PM

Thanks for the reply. It's bed time for me so I'll have to read it carefully again tomorrow.

But

Quote

There is no currying going on here - all functions involved are unary. But you're right that it's piping functions.

Is this beast not binary?

```x >>== f = f x
```

### #4 cfoley

• Cabbage

Reputation: 2391
• Posts: 5,023
• Joined: 11-December 07

Posted 12 November 2014 - 12:50 AM

I tried your do block and it told me that p and p2 were not defined. So I changed it, and now it fails even more spectacularly!

```	treasureMap4 pos = do
x <- pos
y <- stagger x
z <- stagger y
zz <- crawl z
return zz
```

```\$ ghcii.sh drunken-monad.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( drunken-monad.hs, interpreted )

Could not deduce (Monad Position) arising from a do statement
from the context (Num (Position (Position B)/>),
Num (Position B)/>,
Num B)/>
bound by the inferred type of
treasureMap4 :: (Num (Position (Position B)/>), Num (Position B)/>,
Num B)/> =>
Position (Position (Position (Position B)/>)) -> Po
sition b
In a stmt of a 'do' block: x <- pos
In the expression:
do { x <- pos;
y <- stagger x;
z <- stagger y;
zz <- crawl z;
.... }
In an equation for `treasureMap4':
treasureMap4 pos
= do { x <- pos;
y <- stagger x;
z <- stagger y;
.... }
Prelude>
```

My whole code looks like this. Please excuse the commented out code.

```module Main where
data Position t = Position t deriving (Show)

stagger (Position d) = Position (d + 2)
crawl (Position d) = Position (d + 1)

rtn x = x
x >>== f = f x

--treasureMap pos = pos >>==
--				stagger >>==
--				stagger >>==
--				crawl >>==
--				rtn

--treasureMap2 pos = do
--	let { x = stagger pos } ;
--	let { y = stagger x } ;
--	let { z = crawl y } ;
--	rtn z

--treasureMap3 pos = let x = stagger pos
--                       y = stagger x
--                       z = crawl y
--                   in z

treasureMap4 pos = do
x <- pos
y <- stagger x
z <- stagger y
zz <- crawl z
return zz
```

### #5 sepp2k

• D.I.C Lover

Reputation: 2740
• Posts: 4,392
• Joined: 21-June 11

Posted 12 November 2014 - 07:23 AM

cfoley, on 12 November 2014 - 01:33 AM, said:

Quote

There is no currying going on here - all functions involved are unary. But you're right that it's piping functions.

Is this beast not binary?

```x >>== f = f x
```

Yes, it is. And technically it is curried because all infix operators in Haskell are curried, but I did not think that that was what you were referring to. When I said everything was unary, I was referring to stagger and crawl.

Anyway the fact that >>== is a curried function is not relevant to the example.

cfoley, on 12 November 2014 - 08:50 AM, said:

I tried your do block and it told me that p and p2 were not defined.

Oops. That was me being inattentive when renaming my variables. The reply box really needs refactoring support ;-)

Quote

So I changed it, and now it fails even more spectacularly!

Yes, that's because your monad isn't a real monad and do requires a real monad. For a real monad you need >>= and return instead of >>== and rtn and you need to define it as an instance. You also need to define a wrapper type that should be the monad for type m a = a (nor could you define such a type alias in the first place).

I assume your book used this "pseudo monad" to introduce the concept of monads without first having to explain type classes. In order to actually use do notation, you need an actual monad implementing the monad type class. I would hope that the book mentions this.

This post has been edited by sepp2k: 12 November 2014 - 07:23 AM

### #6 sepp2k

• D.I.C Lover

Reputation: 2740
• Posts: 4,392
• Joined: 21-June 11

Posted 12 November 2014 - 07:45 AM

```data Position t = Position t deriving (Show)

return x = Position x
(MyMonad x) >>= f = f x

-- To use stagger and crawl as the right operand to >>=,
-- they actually need to take a t, not a Position
stagger d = return (d + 2)
crawl d = return (d + 1)

-- Without do notation
treasureMap pos =
stagger pos >>=
stagger >>=
crawl >>=
return

-- With do
treasureMapDo pos = do
x <- stagger pos
y <- stagger x
z <- crawl y
return z

-- Or with less redundancy
-- Without do notation
treasureMap2 pos =
stagger pos >>=
stagger >>=
crawl

-- With do
treasureMap2Do pos = do
x <- stagger pos
y <- stagger x
crawl y

```

### #7 cfoley

• Cabbage

Reputation: 2391
• Posts: 5,023
• Joined: 11-December 07