0
votes

I'm working through the following Haskell book - looking at the Chapter Walk the Line:

When I run the following code in ghci:

type Birds = Int  
type Pole = (Birds,Birds)  

x -: f = f x

:{
landLeft :: Birds -> Pole -> Maybe Pole
landLeft n (left,right)
    | abs ((left + n) - right) < 4 = Just (left + n, right)
    | otherwise                    = Nothing
:}

:{
landRight :: Birds -> Pole -> Maybe Pole
landRight n (left,right)
    | abs (left - (right + n)) < 4 = Just (left, right + n)
    | otherwise                    = Nothing
:}

--Failure
(0,0) -: landLeft 1 -: landRight 4 
--(0,0) -: landLeft 1 -: landRight 4 -: landLeft (-1) -: landRight (-2)  
--(0,2)  

I get the error:

Prelude> (0,0) -: landLeft 1 -: landRight 4 

<interactive>:17:24: error:
    • Couldn't match type ‘Maybe Pole’ with ‘(Birds, Birds)’
      Expected type: Maybe Pole -> Maybe Pole
        Actual type: Pole -> Maybe Pole
    • In the second argument of ‘(-:)’, namely ‘landRight 4’
      In the expression: (0, 0) -: landLeft 1 -: landRight 4
      In an equation for ‘it’: it = (0, 0) -: landLeft 1 -: landRight 4

My question is: Why can't ghci match this type?

1
Maybe Pole is not Pole. You can't pass a Maybe Pole to something that takes a Pole. LYAH is going to go into this soon. - AJF
Thanks @AJFarmar - that helpful. Could you expand that in terms of how this can be resolved? - hawkeye
LYAH is going to tell you how to do this, but you could write a :- f = a >>= f and write Just (0,0) instead of (0,0). But once again, LYAH is going to explain this soon. - AJF

1 Answers

2
votes

The variants of landLeft and landRight that work with -: use Pole as return type, not Maybe Pole. Let's view all types at ones:

landLeft  1             ::       Pole -> Maybe Pole
landRight 4             ::       Pole -> Maybe Pole 
(-:)                    :: a -> (a    -> b         ) -> b
(0,0)                   :: Pole
(-:) (0,0)              ::      (Pole -> b         ) -> b
(-:) (0,0) (landLeft 1) ::                              Maybe Pole

Since Maybe Pole isn't Pole, we cannot use (-:) again for landRight. LYAH shows how to deal with those functions: you need a way to use a -> Maybe b functions with Maybe a. That's (>>=) job:

landLeft 1 (0,0) >>= landRight 4

Continue the chapter, as the author immediately tackles your issue:

When we land birds without throwing Pierre off balance, we get a new pole wrapped in a Just. But when many more birds end up on one side of the pole, we get a Nothing. This is cool, but we seem to have lost the ability to repeatedly land birds on the pole. We can't do landLeft 1 (landRight 1 (0,0)) anymore because when we apply landRight 1 to (0,0), we don't get a Pole, but a Maybe Pole. landLeft 1 takes a Pole and not a Maybe Pole. [emphasis mine]