haskell - Are applicative transformers really superfluous? -


there lot of talk applicative not needing own transformer class, this:

class apptrans t     lifta :: applicative f => f -> t f 

but can define applicative transformers don't seem compositions of applicatives! example sideeffectful streams:

data mstream f = mstream (f (a, mstream f a)) 

lifting performs side effect @ every step:

instance apptrans mstream     lifta action = mstream $ (,) <$> action <*> pure (lifta action) 

and if f applicative, mstream f well:

instance functor f => functor (mstream f)     fmap fun (mstream stream) = mstream $ (\(a, as) -> (fun a, fmap fun as)) <$> stream  instance applicative f => applicative (mstream f)     pure = lifta . pure     mstream fstream <*> mstream astream = mstream         $ (\(f, fs) (a, as) -> (f a, fs <*> as)) <$> fstream <*> astream 

i know practical purposes, f should monad:

joins :: monad m => mstream m -> m [a] joins (mstream stream) =     (a, as) <- stream     aslist <- joins     return $ : aslist 

but while there monad instance mstream m, it's inefficient. (or incorrect?) applicative instance useful!

now note usual streams arise special cases identity functor:

import data.functor.identity type stream = mstream identity 

but composition of stream , f not mstream f! rather, compose stream f a isomorphic stream (f a).

i'd know whether mstream composition of 2 applicatives.

edit:

i'd offer category theoretic viewpoint. transformer "nice" endofunctor t on category c of applicative functors (i.e. lax monoidal functors strength), natural transformation lifta identity on c t. more general question useful transformers exist not of form "compose g" (where g applicative). claim mstream 1 of them.

great question! believe there 2 different parts of question:

  1. composing existing applicatives or monads more complex ones.
  2. constructing all applicatives/monads given starting set.

ad 1.: monad transformers essential combining monads. monads don't compose directly. seems there needs bit of information provided monad transformers tells how each monad can composed other monads (but information somehow present, see is there monad doesn't have corresponding monad transformer?).

on other hand, applicatives compose directly, see data.functor.compose. why don't need applicative transformers composition. they're closed under product (but not coproduct).

for example, having infinite streams data stream = cons (stream a) , applicative g, both stream (g a) , g (stream a) applicatives.

but though stream monad (join takes diagonal of 2-dimensional stream), composition monad m won't be, neither stream (m a) nor m (stream a) monad.

furthermore can see, they're both different mstream g (which close listt done right), therefore:

ad 2.: can applicatives constructed given set of primitives? apparently not. 1 problem constructing sum data types: if f , g applicatives, either (f a) (g a) won't be, don't know how compose right h <*> left x.

another construction primitive taking fixed point, in mstream example. here might attempt generalize construction defining like

newtype fix1 f = fix1 { unfix1 :: f (fix1 f) }  instance (functor (f (fix1 f))) => functor (fix1 f)     fmap f (fix1 a) = fix1 (fmap f a)  instance (applicative (f (fix1 f))) => applicative (fix1 f)     pure k = fix1 (pure k)     (fix1 f) <*> (fix1 x) = fix1 (f <*> x) 

(which requires not-so-nice undecidableinstances) , then

data mstream' f g = mstream (f (a, g a))  type mstream f = fix1 (mstream' f) 

Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -