I've been working on understanding Monads in Haskell a bit better so I've started reading Philip Wadler's paper Monads for functional programming. In order to internalize the principles a bit better, and expose myself to as much Haskell code as possible, I decided I would code up and test all the examples as I go through the paper.
Right off 2.2 Variation one: Exceptions is giving me a little trouble. Here is my code.
data Term = Con Int | Div Term Term
data M a = Raise Exception | Return a
type Exception = String
answer, error_ :: Term
answer = (Div (Div (Con 1972) (Con 2)) (Con 23))
error_ = (Div (Con 1) (Con 0))
eval :: Term -> M Int
eval (Con a) = Return a
eval (Div t u) = case eval t of
Raise e -> Raise e
Return a ->
case eval u of
Raise e -> Raise e
Return b ->
if b == 0
then Raise "divide by zero"
else Return (a `div` b)
I can load the code into GHCi, but when I try to run
eval answer
it throws the error
No instance for (Show (M Int)) arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it
I read this post which explains why ‘print’ is being called and concluded that maybe I needed to add an instance to Show for M a. But when I added
instance Show (M a) where
show (M a) = show a
to my code I tried to reload the file I got this error.
Not in scope: data constructor ‘M’
This confused me at first but this post explains that I was defining a type constructor not a data constructor.
Anyway, I feel like I am going down a rabbit hole that may or may not have the solution and I figured I'd post the question over here. My code looks to be line-for-line the same as his code. What changes do I need to make to make the code run in GHCi?
The added Show
instance will not work for two reasons:
a
of M a
is an instance of Show
; andM
data type has no data constructor M
, it has a Raise
, and a Return
.So a straightforward implementation would look like:
instance Show a => Show (M a) where
show (Raise a) = "Raise " ++ show a
show (Return a) = "Return " ++ show a
But we can save us the trouble, and let Haskell automatically derive an instance for Show
with:
data M a = Raise Exception | Return a deriving Show