Reputation: 163
I'm in the process of learning applicative functors in Haskell from learn-you-a-haskell book. But whenever I try to type in the following code into ghci:
:{
instance Applicative ZipList where
pure x = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)
:}
I get three errors:
<interactive>:137:22: error:
Not in scope: type constructor or class ‘ZipList’
<interactive>:139:9: error:
Not in scope: data constructor ‘ZipList’
<interactive>:139:24: error:
Not in scope: data constructor ‘ZipList’
I tried loading:
import Data.List
import Data.Char
I tried searching for ZipList without success.
I tried running the next few expressions without instance declaration:
getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]
But they also fail with the following errors:
<interactive>:142:1: error:
Variable not in scope: getZipList :: f0 Integer -> t
<interactive>:142:22: error:
Data constructor not in scope: ZipList :: [Integer] -> f0 Integer
<interactive>:142:42: error:
Data constructor not in scope: ZipList :: [Integer] -> f0 Integer
I also tried searching and found this answer: Haskell ZipList Applicative But it doesn't help me.
Upvotes: 1
Views: 307
Reputation: 7014
ZipList
already exists in Control.Applicative
and uses the Applicative
instanced defined there. You can't redefine that instance.
>> import Control.Applicative
>> getZipList $ (+) <$> ZipList [1,2,3] <*> ZipList [100,100,100]
[101,102,103]
>> getZipList $ liftA2 (+) (ZipList [1,2,3]) (ZipList [100,100,100])
[101,102,103]
To define your own you must define a new ZipList'
that we read "ZipList
prime":
-- >> getZipList' $ (+) <$> ZipList' [1,2,3] <*> ZipList' [100,100,100]
-- [101,102,103]
newtype ZipList' a = ZipList' { getZipList' :: [a] }
instance Functor ZipList' where
fmap f (ZipList' as) = ZipList' (fmap f as)
instance Applicative ZipList' where
pure a = ZipList' (repeat a)
ZipList' fs <*> ZipList' xs = ZipList' (zipWith (\f x -> f x) fs xs)
You can also derive Functor
. I recommend writing instance signatures for fmap
, pure
, (<*>)
:
{-# Language DeriveFunctor #-}
{-# Language DerivingStrategies #-}
{-# Language InstanceSigs #-}
import Control.Applicative (liftA2)
newtype ZipList' a = ZipList' { getZipList' :: [a] }
deriving
stock Functor
-- instance Functor ZipList' where
-- fmap :: (a -> a') -> (ZipList' a -> ZipList' a')
-- fmap f (ZipList' as) = ZipList' (fmap f as)
instance Applicative ZipList' where
pure :: a -> ZipList' a
pure a = ZipList' (repeat a)
(<*>) :: ZipList' (a -> b) -> ZipList' a -> ZipList' b
ZipList' fs <*> ZipList' xs = ZipList' (zipWith ($) fs xs)
liftA2 :: (a -> b -> c) -> (ZipList' a -> ZipList' b -> ZipList' c)
liftA2 (·) (ZipList' as) (ZipList' bs) = ZipList' (zipWith (·) as bs)
You can write (\f x -> f x)
as ($)
or id
.
Upvotes: 2