
I'm following the CIS194 lectures and exercises. In particular, in one of the Applicative lectures [0] we're asked to implement mapA and sequenceA, from the name and given type signature alone. I renamed them mapA' and sequenceA' to avoid name clashes, and defined: import Control.Applicative mapA' :: Applicative f => (a -> f b) -> ([a] -> f [b]) mapA' f = sequenceA' . map f sequenceA' :: Applicative f => [f a] -> f [a] sequenceA' = foldr (\fa fla -> (:) <$> fa <*> fla) (pure []) These implementations seem to be correct, though undoubtedly not the nicest. Now, I ask for a type in ghci:
:t mapA' pure [1..5] mapA' pure [1..5] :: (Enum b, Num b, Applicative f) => f [b]
And so I try the following:
mapA' pure [1..5] :: [[Int]] [[1,2,3,4,5]] take 5 . getZipList $ (mapA' pure [1..5] :: ZipList [Int]) [[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5]] mapA' pure [1..5] :: Maybe [Int] Just [1,2,3,4,5]
That makes sense. But I don't understand the following:
mapA' pure [1..5] [1,2,3,4,5]
:t pure
Which Applicative instance is being used here? The type test above says my expression should have type f [b], where f is an Applicative and b is a Num, but all I see is a result of type [b] when I compute mapA' pure [1..5]. What's going on? More simply pure :: Applicative f => a -> f a
pure [1..5] [1,2,3,4,5]
a must match a list of Nums, but then where did f go? Is ghci using some default instance? Actually, after I add the following lines to my source file: ggg = pure [1..5] hhh = mapA' pure [1..5] I get the errors: No instance for (Applicative f0) arising from a use of ‘pure’ No instance for (Applicative f1) arising from a use of ‘mapA'’ respectively. That makes sense to me. Graham [0] http://www.seas.upenn.edu/~cis194/fall14/spring13/lectures/11-applicative2.h...

On Sun, Nov 15, 2015 at 9:29 AM, Graham Gill
:t pure
More simply pure :: Applicative f => a -> f a
pure [1..5] [1,2,3,4,5]
a must match a list of Nums, but then where did f go? Is ghci using some default instance?
Yes it is. The default instance is IO. It's a common gotcha, see https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/interactive-... and the example of how "return True" defaults to IO Bool. Might I compliment you on this: sequenceA' :: Applicative f => [f a] -> f [a] sequenceA' = foldr (\fa fla -> (:) <$> fa <*> fla) (pure []) There are strong arguments that this is the best way of writing sequenceA. -- Kim-Ee

On 11/14/2015 9:58 PM, Kim-Ee Yeoh wrote: [...]
Yes it is. The default instance is IO. It's a common gotcha, see
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/interactive-... https://downloads.haskell.org/%7Eghc/latest/docs/html/users_guide/interactiv...
and the example of how "return True" defaults to IO Bool.
Thanks Kim-Ee, that makes it clear.
Might I compliment you on this:
sequenceA' :: Applicative f => [f a] -> f [a] sequenceA' = foldr (\fa fla -> (:) <$> fa <*> fla) (pure [])
There are strong arguments that this is the best way of writing sequenceA.
-- Kim-Ee
Thanks, but it just seemed the most straightforward thing to do at my present level of understanding. Are there substantially different ways to define sequenceA? I'm interested to read the arguments if you can give a pointer to a post somewhere. Graham
participants (2)
-
Graham Gill
-
Kim-Ee Yeoh