Reputation: 5201
I working through the Paul Hudaks highly recommended book Haskell School of Expression. In the 13:th chapter I stumbled across this definition
type Time = Float
newtype Behavior a = Beh (Time -> a)
The author has declared several instances of the newtype Behavior
: Eq
, Show
, Num
, Fractional
and Floating
, but among these it´s only one function in one of these instance declarations that is bugging me:
instance Num a => Num (Behavior a) where
(+) = lift2 (+) -- This one!
fromInteger = lift0 . fromInteger
lift0 :: a -> Behavior a
lift0 x = Beh (\t -> x)
lift2 :: (a -> b -> c) -> (Behavior a -> Behavior b -> Behavior c)
lift2 g (Beh a) (Beh b)
= Beh (\t -> g (a t) (b t)) -- Or actually this one.
time :: Behavior Time
time = Beh (\t -> t)
The author describes, after this, that with these new function declarations we can now write time + 5
and thus lift the (+)
operator into the realm of Behavior, or something in that fashion. That sounds all good to me, so I nod and smile as I read along. Suddenly, the author explains that: (time + 5)
is equivalent to Beh (\t -> t + 5)
, which sounds totally whacked. He actually even provides this unfolding of the expressions to prove it:
time + 5
==> { unfold overloadings for time, (+), and 5 }
(lift2 (+)) (Beh (\t -> t)) (Beh (\t -> 5))
==> { unfold lift2 }
(\ (Beh a) (Beh b) -> Beh (\t -> a t + b t)) (Beh (\t -> t)) (Beh (\t -> 5))
==> { unfold anonymous function }
Beh (\t -> (\t -> t) t + (\t -> 5) t )
==> { unfold two anonymous functions }
Beh (\t -> t + 5)
This is more specifically what I´m having trouble understanding. To me the correct statement would be: time + (Beh 5)
is equivalent to Beh (\t -> t + 5)
. But when I infer the type in ghci it tells me (of course) that the author is right and that I´m stupid in some formal way. Can someone please explain it to me.
Upvotes: 3
Views: 106
Reputation: 835
(+)
has type Num a => a -> a -> a
. Here a
is Behavior Float
. The literal 5
in your code is converted to Behavior Float
with fromInteger
, which should look like fromInteger n = Beh (\t -> fromInteger n)
.
Beh 5
wouldn't typecheck since Beh
wraps a function of type Float -> a
, not a number.
Upvotes: 5