Reputation: 2222
The Haskell book Haskell Programming from First Principles has an exercise which asks me to instance Applicative
on the datatype List
:
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
instance Functor List where
fmap _ Nil = Nil
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
instance Applicative List where
pure x = Cons x Nil
Nil <*> _ = Nil
_ <*> Nil = Nil
Cons f fs <*> Cons x xs = Cons (f x) ((fmap f xs) <> (fs <*> xs))
I wrote the above code and found I must first instance Semigroup
to let the <>
operator work.
Can this be implemented without instance Semigroup
first?
Upvotes: 1
Views: 1382
Reputation: 4360
Well you use something called <>
and Haskell knows that this thing (specifically the definition of <>
that you have imported as you haven’t defined the operator anywhere) requires a semigroup. The solution is to use a different name or define it locally:
Cons f fs <*> xs = (f <$> xs) <> (fs <*> xs)
where xs <> Nil = xs
Nil <> xs = xs
Cons x xs <> ys = Cons x (xs <> ys)
Upvotes: 0
Reputation: 476709
Yes. You here use the (<>)
function in your definition:
instance Applicative List where
pure x = Cons x Nil
Nil <*> _ = Nil
_ <*> Nil = Nil
Cons f fs <*> Cons x xs = Cons (f x) ((fmap f xs) <> (fs <*> xs))
-- ^ call to the (<>) function
so you can replace this with a call to another function:
instance Applicative List where
pure x = Cons x Nil
Nil <*> _ = Nil
_ <*> Nil = Nil
Cons f fs <*> Cons x xs = Cons (f x) (append (fmap f xs) (fs <*> xs))
where append = ...
Note however that here you probably have implement a different function than the one you intend here. Here you implemented a function that for two lists [f1, f2, f3]
and [x1, x2, x3, x4]
, will calculate a list with the "upper triangle" of the matrix of fs
and xs
, so this will result in [f1 x1, f1 x2, f1 x3, f1 x4, f2 x2, f2 x3, f2 x4, f3 x3, f3 x4]
. Note that here f2 x1
, f3 x1
and f3 x2
are missing.
Upvotes: 2