我目前正在处理Data.Fresh
和Control.Monad.Trans.Fresh
。定义用于生成新变量的接口,以及实现此接口的monad转换器。
我最初认为可以为Applicative
实施FreshT v m
个实例,只要求Applicative m
存在。但是,我卡住了,似乎我需要Monad m
。不相信我的Haskell-fu,然后我转向变形金刚包,并对我在Control.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
答案 0 :(得分:13)
考虑您有两个功能:
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(无论你使用的是什么,它都会以m s
的形式存在,所以你将无法申请值为g
)。
您可以使用定义并使用free monad但是对于状态崩溃,您需要join
。
答案 1 :(得分:6)
Applicative
转换器虽然无法为StateT
定义应用变换器,但可以定义一个有效的较弱变量。我们可以使用s -> m (a, s)
或等效m
,而不是m (s -> (a, s))
,状态决定下一个效果(因此m (State s a)
必须是monad)。
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
定义Functor
和Applicative
只是将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
更新:实际上上面没有必要,因为两个应用函子的组合总是一个应用函子(不像monads)。我们的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)
答案 2 :(得分:5)
虽然如前面的答案所述,这个实例一般无法定义,但值得注意的是,当f
为Applicative
且s
为{{1}时},Monoid
也是StateT s f
,因为它可以被视为应用函子的组合:
Applicative