Problems determining the applicative instance

Suppose I want to define a data type indexed by two layer environments. Sort of:

data Woo s a = Woo a | Waa s a

data Foo (s :: *) (env :: [(Symbol,*)]) (env' :: [(Symbol,*)]) (a :: *) =
     Foo { runFoo :: s -> Sing env -> (Woo s a, Sing env') }

The idea is that envthis is an input environment, and env'is an output. Thus, the type Fooacts as an indexed state monad . So far, so good. My problem is how can I show what Foois an applicative functor. The obvious attempt is

instance Applicative (Foo s env env') where
    pure x = Foo (\s env -> (Woo x, env))
    -- definition of (<*>) omitted.

but the GHC complains that it is purenot typed, as it indicates the type

    pure :: a -> Foo s env env a

instead of the expected type

    pure :: a -> Foo s env env' a

. , Applicative Foo, ? googled , , , . - - ?

+4
2

Foo , Atkey , (, ) .

- - , . , , .

class IFunctor f where
    imap :: (a -> b) -> f x y a -> f x y b

class IFunctor f => IApplicative f where
    ipure :: a -> f x x a
    (<**>) :: f x y (a -> b) -> f y z a -> f x z b

class IApplicative m => IMonad m where
    (>>>=) :: m x y a -> (a -> m y z b) -> m x z b

, x y y z, bind >>>= , x z.

, ipure f x x a. , ipure, . id.

, , - newtype IState i o a = IState (i -> (o, a)), i o. , .

newtype IState i o a = IState { runIState :: i -> (o, a) }

instance IFunctor IState where
    imap f s = IState $ \i ->
        let (o, x) = runIState s i
        in (o, f x)

instance IApplicative IState where
    ipure x = IState $ \s -> (s, x)
    sf <**> sx = IState $ \i ->
        let (s, f) = runIState sf i
            (o, x) = runIState sx s
        in (o, f x)

instance IMonad IState where
    s >>>= f = IState $ \i ->
        let (t, x) = runIState s i
        in runIState (f x) t

, . IMonad, -esque-, , : , , . IMonad Foo.

, Woo s a (a, Maybe s), Writer . , Monad (Woo s) , .

type Woo s a = Writer (First s) a

First Maybe monoid, , Woo. Last.

, Writer Traversable. , Writer , : a, . , Functor f.

-- cf. traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
traverseW :: Functor f => (a -> f b) -> Writer w a -> f (Writer w b)
traverseW f m = let (x, w) = runWriter m
                in fmap (\x -> writer (x, w)) (f x)

.

Foo s IFunctor. Writer s: fmap Writer .

newtype Foo (s :: *) (env :: [(Symbol,*)]) (env' :: [(Symbol,*)]) (a :: *) =
    Foo { runFoo :: s -> Sing env -> (Woo s a, Sing env') }

instance IFunctor (Foo s) where
    imap f foo = Foo $ \s env ->
        let (woo, env') = runFoo foo s env
        in (fmap f woo, env')

Foo Functor, traverseW.

instance Functor (Foo s x y) where
    fmap = imap

Foo s IApplicative. Writer s Applicative, Woo. Monoid s.

instance IApplicative (Foo s) where
    ipure x = Foo $ \s env -> (pure x, env)
    foo <**> bar = Foo $ \s env ->
        let (woof, env') = runFoo foo s env
            (woox, env'') = runFoo bar s env'
        in (woof <*> woox, env'')

Foo s IMonad. , Writer s Monad. traverseW a Kleisli f.

instance IMonad (Foo s) where
    foo >>>= f = Foo $ \s env ->
        let (woo, env') = runFoo foo s env
            (woowoo, env'') = runFoo (traverseW f woo) s env'
        in (join woowoo, env'')

. , , - . , Foo :

type Foo s env env' = ReaderT s (IStateT (Sing env) (Sing env') (WriterT (First s) Identity))

, . >>>= , , , , , . .

, . McBride IMonad :

type f ~> g = forall x. f x -> g x

class IMonad m where
    ireturn :: a ~> m a
    (=<?) :: (a ~> m b) -> (m a ~> m b)

:

class IMonadTrans t where
    ilift :: IMonad m => m a ~> t m a
+5

, Sing env' - , Monoid, :

  • Sing env' (, mempty)
  • Sing env' <*> (, mappend).

s <*>, , SemiGroup -, , , , Monoid.

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveFunctor #-}
module SO37860911 where
import GHC.TypeLits (Symbol)
import Data.Singletons (Sing)

data Woo s a = Woo a | Waa s a 
  deriving Functor

instance Monoid s => Applicative (Woo s) where
  pure = Woo 
  Woo f <*> Woo a = Woo $ f a 
  Waa s f <*> Woo a = Waa s $ f a 
  Woo f <*> Waa s a = Waa s $ f a 
  Waa s f <*> Waa s' a = Waa (mappend s s') $ f a 

data Foo (s :: *) (env :: [(Symbol,*)]) (env' :: [(Symbol,*)]) (a :: *) =
     Foo { runFoo :: s -> Sing env -> (Woo s a, Sing env') }
  deriving Functor

instance (Monoid s, Monoid (Sing env')) => Applicative (Foo s env env') where
  pure a = Foo $ \_s _env -> (pure a, mempty)
  Foo mf <*> Foo ma = Foo $ \s env -> case (mf s env, ma s env) of
    ((w,e), (w',e')) -> (w <*> w', e `mappend` e')
+1

All Articles