How does `sequenceA`

Am I new to Haskell and trying to figure out how this works?

sequenceA [(+3),(+2),(+1)] 3

I started by defining

sequenceA :: (Applicative f) => [f a] -> f [a]  
sequenceA [] = pure []  
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs

And then the expanded recursion into this

(:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> pure [] 
(:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> []

But here I do not understand why the operator of the applicative functor will be called <*>for ((->) r)or for[]

(:) <$> (+1) <*> []

Can someone go step by step and parsing sequenceA [(+3),(+2),(+1)] 3step by step? Thanks.

+4
source share
3 answers

uses instance Applicative ((->) a).

Try this in ghci:

Prelude> :t [(+3),(+2),(+1)]
[(+3),(+2),(+1)] :: Num a => [a -> a]

Prelude> :t sequenceA
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)

and the pattern matches the type of argument: t = [], f = (->) a and the applicative constraint is at f.

+2
source

This can be seen from the type of sequence A:

sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)

Traverable, Applicative.

, sequenceA (Num a) => [a -> a], Traversable, Applicative. .

, sequenceA [(+3),(+2),(+1)], :

sequenceA [(+3),(+2),(+1)] = (:) <$> (+3) <*> sequenceA [(+2),(+1)]
sequenceA [(+2),(+1)]      = (:) <$> (+2) <*> sequenceA [(+1)]
sequenceA [(+1)]           = (:) <$> (+1) <*> sequenceA []
sequenceA []               = pure []

. pure [] . , ((->) r). - sequenceA [] = pure [] = const [].

3 :

sequenceA [(+1)] = (:) <$> (+1) <*> const []

<$> <*> . (+1) const [] , (:)

sequenceA [(+1)] , Num a => a, (+1), , \x -> (:) ((1+) x) (const [] x)= \x -> [(+1) x].

sequenceA [(+3), (+2), (+1)]. , , (:) : \x -> [(+3) x, (+2) x, (+1) x].

+6

, , sequenceA [(+1)] BOTH (+1) const [], . , pure [] = const [].

sequenceA [(+1)] = (:) <$> (+1) <*> const []

lambdas ( , ):

sequenceA [(+1)] = \b c -> ( (:) b c ) <$> ( \a -> (+1) a ) <*> ( \a -> const [] a )

(<$>) (<*>) infixl 4. , , .. (<$>).

(<$>) :: Functor f => (a -> b) -> f a -> f b.

<$> , (+1) ((->) r), OR \a -> - \b c -> ( (:) b c ), b, ( \a, ):

sequenceA [(+1)] = \a c -> ( (:) ((+1) a) c ) <*> ( \a -> const [] a )

, (:) c, (+1) a. .

, : (<*>) :: f (a -> b) -> f a -> f b. f - \a ->.

, \a ->. a , , a , - . . a, , , . \a -> ( <*>), :

( \c -> ( (:) ((+1) a) c ) ) (const [] a)

= ( (:) ((+1) a) (const [] a) ) -- Ignore those a's, they're placeholders.

, <*>, - \a ->:

sequenceA [(+1)] = \a -> ( (:) ((+1) a) (const [] a) )

Sugaring :

sequenceA [(+1)] = \a -> (+1) a : const [] a

Cm! It makes sense that the argument sequenceA [(+1)]for both to (+1)and for const. For example, application 2 gives:

sequenceA [(+1)] 2 = (+1) 2 : const [] 2

Remember that const a b :: a -> b -> aand therefore simply ignores it:

sequenceA [(+1)] 2 = 3 : []

OR, more sweetly:

sequenceA [(+1)] 2 = [3]
+1
source

Source: https://habr.com/ru/post/1623047/


All Articles