Reputation: 31918
Here is my custom List class used to create a custom ZipList class. I want to create a ZipList' applicative instance.
import Control.Applicative
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
instance Functor List where
fmap f (Cons x xs) = Cons (f x) (fmap f (Cons (head' xs) (tail' xs)))
fmap _ Nil = Nil
instance Applicative List where
pure x = Cons x Nil
(<*>) fs xs = Cons (head' fs $ head' xs) ((<*>) (tail' fs) (tail' xs))
head' :: List a -> a
head' (Cons a _) = a
tail' :: List a -> List a
tail' (Cons _ l) = l
take' :: Int -> List a -> List a
take' 0 _ = Nil
take' _ Nil = Nil
take' i xs = Cons (head' xs) (take' (i-1) (tail' xs))
newtype ZipList' a =
ZipList' (List a)
deriving (Eq, Show)
instance Functor ZipList' where
fmap f (ZipList' xs) = ZipList' $ fmap f xs
instance Applicative ZipList' where
pure x = ZipList' (Cons x Nil)
(<*>) fs xs = ZipList' (go fs xs)
where go gs ys = Cons (head' gs $ head' ys) (go (tail' gs) (tail' ys))
go Nil _ = Nil
go _ Nil = Nil
The error I am getting is:
chap17/ZipList_applicative.hs:38:30: Couldn't match expected type ‘List (r0 -> b)’ …
with actual type ‘ZipList' (a -> b)’
Relevant bindings include
xs :: ZipList' a
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:12)
fs :: ZipList' (a -> b)
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:9)
(<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:3)
In the first argument of ‘go’, namely ‘fs’
In the first argument of ‘ZipList'’, namely ‘(go fs xs)’
chap17/ZipList_applicative.hs:38:33: Couldn't match expected type ‘List r0’ …
with actual type ‘ZipList' a’
Relevant bindings include
xs :: ZipList' a
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:12)
fs :: ZipList' (a -> b)
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:9)
(<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
(bound at /Users/ebs/code/haskell/book/chap17/ZipList_applicative.hs:38:3)
In the second argument of ‘go’, namely ‘xs’
In the first argument of ‘ZipList'’, namely ‘(go fs xs)’
Compilation failed.
It says that it expects a List (r0 -> b) type from go, not ZipList'. I do not get why, go returns a List, not a ZipList'...
Upvotes: 1
Views: 157
Reputation: 30103
Your go
takes ZipList
as input, but in (<*>) fs xs
xs
and fs
are ZipList'
s. You should unwrap the newtype:
ZipList' fs <*> ZipList' xs = ZipList' (go fs xs)
Also, your go
is wrong. It fails with a runtime error whenever the program evaluates an empty list in either arguments, because the go gs ys
case matches everything, and the cases after it are unreachable. You should instead do something like this:
go (Cons f fs) (Cons x xs) = Cons (f x) (go fs xs)
go _ _ = Nil
As a general rule, you should avoid head
, tail
, and other partial functions (i. e. functions that possibly throw exceptions). Pattern matching on Cons x xs
binds both the head and the tail, so there isn't much use for head
and tail
thereafter. It's very rare that the use of partial functions is truly justified.
Upvotes: 5