简体   繁体   中英

Instance applicative on datatype `List`

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?

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) ( (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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM