Подтвердить что ты не робот

Functor/Прикладные примеры для штата в Хаскелле

После прочтения (и снятия некоторых разделов) бумаги Вадлера на монадах я решил более подробно проработать статью, указав функтор и аппликативные экземпляры для каждой из монад, которые он описывает. Использование синонима типа

type M a = State -> (a, State)
type State = Int

Wadler использует для определения монады состояния, у меня есть следующее (используя связанные имена, чтобы я мог позже определить их с объявлением newtype).

fmap' :: (a -> b) -> M a -> M b
fmap' f m = \st -> let (a, s) = m st in (f a, s)

pure' :: a -> M a
pure' a = \st -> (a, st)

(<@>) :: M (a -> b) -> M a -> M b
sf <@> sv = \st -> let (f, st1) = sf st
                       (a, st2) = sv st1
                    in (f a, st2)

return' :: a -> M a
return' a = pure' a

bind :: M a -> (a -> M b) -> M b
m `bind` f = \st -> let (a, st1) = m st
                        (b, st2) = f a st1
                     in (b, st2)

Когда я переключаюсь на использование конструктора типа в объявлении newtype, например,

newtype S a = S (State -> (a, State))

все разваливается. Все это просто небольшая модификация, например,

instance Functor S where
 fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s)) 

instance Applicative S where
 pure a = S (\st -> (a, st))

однако ничего не работает в GHC из-за того, что выражение лямбда скрыто внутри этого конструктора типов. Теперь единственным решением, которое я вижу, является определение функции:

isntThisAnnoying s (S m) = m s

чтобы привязать s к 'st' и фактически вернуть значение, например,

fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))

Есть ли другой способ сделать это, который не использует эти вспомогательные функции?

4b9b3361

Ответ 1

Если вы посмотрите здесь, вы увидите, что они определяют его следующим образом:

newtype State s a = State { runState :: (s -> (a,s)) }

чтобы дать внутреннему лямбда имя.

Ответ 2

Обычный способ - определить newtype newtype S a = S {runState : State -> (a, State)}. Затем вместо isntThisAnnoying s (S m) вы можете написать runState t s, где t совпадает с S m.
Вы должны использовать newtype, потому что синонимы типов не могут быть экземплярами typeclass.