18

我目前正在研究Data.Freshand Control.Monad.Trans.Fresh,分别是。定义一个用于生成新变量的接口,以及一个实现该接口的 monad 转换器。

我最初认为可以通过存在的唯一要求Applicative为我实现实例。但是,我被卡住了,似乎我需要 require 。不相信我的 Haskell-fu,然后我转向了变形金刚包,并对我在and中发现的内容感到惊讶:FreshT v mApplicative mMonad mControl.Monad.Trans.State.Lazy.Strict

instance (Functor m, Monad m) => Applicative (StateT s m) where
    pure = return
    (<*>) = ap

所以这是我的问题:是否可以使用以下实例头创建具有等效语义的实例?

instance (Applicative m) => Applicative (StateT s m) where
4

3 回答 3

16

考虑您有两个功能:

 f :: s -> m (s, a -> b)
 g :: s -> m (s, a)

你想创建一个函数h = StateT f <*> StateF g

 h :: s -> m (s, b)

从上面你有一个s你可以传递给f所以你有:

 f' :: m (s, a -> b)
 g :: s -> m (s, a)

但是,要s摆脱f'你需要 Monad(无论你用 applicative 做什么,它仍然是形式,m s所以你不能将值应用到g)。

您可以使用定义并使用免费的 monad,但对于您需要的状态崩溃join

于 2013-09-07T13:40:59.883 回答
6

Applicative变压器的较弱变体

虽然不可能为 定义一个适用的转换器StateT,但可以定义一个更弱的变体。我们可以使用, 或等效地使用 ,而不是s -> m (a, s)状态决定下一个效果的地方(因此m必须是单子)。m (s -> (a, s))m (State s a)

import Control.Applicative
import Control.Monad
import Control.Monad.State
import Control.Monad.Trans

newtype StateTA s m a = StateTA (m (State s a))

这严格地弱于StateT。每个StateTA都可以制成StateT(但反之亦然):

toStateTA :: Applicative m => StateTA s m a -> StateT s m a
toStateTA (StateTA k) = StateT $ \s -> flip runState s <$> k

定义FunctorandApplicative只是将操作提升State到底层的问题m

instance (Functor m) => Functor (StateTA s m) where
    fmap f (StateTA k) = StateTA $ liftM f <$> k
instance (Applicative m) => Applicative (StateTA s m) where
    pure = StateTA . pure . return
    (StateTA f) <*> (StateTA k) = StateTA $ ap <$> f <*> k    

我们可以定义一个应用变体lift

lift :: (Applicative m) => m a -> StateTA s m a
lift = StateTA . fmap return

更新:实际上以上不是必需的,因为两个应用函子的组合始终是一个应用函子(与单子不同)。我们StateTA与 同构Compose m (State s),自动为Applicative

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)

因此我们可以只写

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Applicative
import Control.Monad.State
import Data.Functor.Compose

newtype StateTA s m a = StateTA (Compose m (State s) a)
    deriving (Functor, Applicative)
于 2013-09-07T17:37:18.210 回答
5

尽管如上一个答案中所述,此实例不能一般定义,但值得注意的是,当fisApplicativesis a时MonoidStateT s f也是Applicative,因为它可以被视为应用函子的组合:

StateT s f = Reader s `Compose` f `Compose` Writer s
于 2013-09-07T14:06:39.123 回答