Я не могу найти ни одного возможного экземпляра, который просто не отбрасывает состояние внутреннего контейнера. Это неудивительно, поскольку возврат чистой функции, привязанной к данным, должен возвращать одно и то же каждый раз при вызове ввода, независимо от того, вызывалась ли она ранее, на что вы намекаете в своих комментариях.
Сами по себе
Единственные Monad
экземпляры, которые я могу придумать, отбрасывают последующие состояния для внутреннего контейнера.
instance Monad (SF e) where
return a = SF . const $ (a, return a)
(>>=) sa f = SF go
where
go e =
let
(a, sa') = run sa e
sb = f a
(b, _) = run sb e
in
(b, sa' >>= f)
or
join :: SF e (SF e a) -> SF e a
join ssa = SF go
where
go e =
let
(sa, ssa') = run ssa e
(a, _) = run sa e
in
(a, join ssa')
Их можно выразить более кратко, используя экземпляр Monad для функций
instance Monad (SF e) where
return a = SF . const $ (a, return a)
(>>=) sa f = SF {
run =
do
(a, sa') <- run sa
(b, _) <- run (f a)
return (b, sa' >>= f)
}
Мы можем поискать в другом месте что-то немного другое.
Экземпляр функциональной монады
Ваша newtype SF e a = SF { run :: e -> (a, SF e a) }
очень близка к функции от e
до a
. Для экземпляра монады для функций единственным разумным >>=
является передача аргумента как внутренней, так и внешней функциям. Это то, что мы уже придумали. Посмотрим, сможем ли мы придумать что-нибудь еще.
Штат
Ваш код чем-то похож на Преобразователь монады StateT применяется к экземпляру монады для функций. К сожалению, это не дает того, что мы ищем.
Рассмотрим следующее (преобразователь монады StateT):
newtype StateT s m a = StateT { runStateT :: s -> m (a, s)}
Применяется к типу ((->) e)
функции, принимающей аргумент `e.
StateT s ((->) e) a
имеет единственный конструктор StateT { runStateT :: s -> e -> (a, s) }
.
Это отличается от вашего типа тем, что должно быть предоставлено начальное состояние, и состояние отслеживается явно, а не уже включено в возвращаемое следующее значение. Давайте посмотрим, каким будет экземпляр Monad
для этого. Экземпляр Monad
StateT
находится
instance (Monad m) => Monad (StateT s m) where
return a = state $ \s -> (a, s)
m >>= k = StateT $ \s -> do
~(a, s') <- runStateT m s
runStateT (k a) s'
state f = StateT (return . f)
В сочетании с экземпляром для (->) e
instance Monad ((->) e) where
return = const
(>>=) x y z = y (x z) z
Мы получим следующее, где do
сбрасывает работу на экземпляр для ((->) e)
instance Monad (StateT s ((->) e) where
return a = StateT (const . (\s -> (a, s)))
m >>= k = StateT $ \s e ->
let (a, s`) = runStateT m s e
in runStateT (k a) s` e
Это выглядит совсем иначе. Мы не теряем историю ни одного государства. Здесь происходит то, что состояние внутреннего контейнера передается ему из внешнего контейнера, и два контейнера должны иметь один и тот же тип состояния, чтобы это работало. Это совсем не то, чего мы хотим.
Что-то новое
Что произойдет, если мы попытаемся сделать что-то вроде StateT
из вашего типа? Мы хотели бы иметь возможность передать тип (->) e
и получить структуру, подобную вашей. Мы создадим что-то под названием SFT m a
, чтобы SFT ((-> e) a
имел ту же структуру, что и SF e a
.
newtype SF e a = SF { run :: e -> (a, SF e a)
newtype SFT m a = SFT { unSFT :: m (a, SFT m a) }
Мы можем заменить тип, полученный путем применения SFT
к (->) e)
вместо SF
, примененного к e
.
SF e a -- is replaced by
SFT ((->) e) a
У этого есть один конструктор
SF { run :: e -> (a, SF e a) }
SFT { unSFT :: e -> (a, SFT ((->) e) a) }
Это не дает нового понимания, единственный Monad
пример, который я могу придумать, поскольку он почти идентичен исходному.
instance Monad m => Monad (SFT m) where
return a = SFT . return $ (a, return a)
(>>=) sa f = SFT {
unSFT =
do
(a, sa') <- unSFT sa
(b, _) <- unSFT (f a)
return (b, sa' >>= f)
}
person
Cirdec
schedule
28.03.2014
newtype SF a b = SF { run :: a -> (b, SF a b) }
, вы можете заметить, что экземплярMonad
всегда вызывает событиеa
как во внутреннем, так и во внешнем контейнерах для каждого события. Следовательно, состояние внутреннего контейнера не будет иметь значения. - person Cirdec   schedule 28.03.2014join
в FRP: stackoverflow.com/questions/20890439/behavior-now-in-frp/ - person Cirdec   schedule 28.03.2014ArrowApply
/Monad
. - person Xeo   schedule 28.03.2014