Функтор / Применительные экземпляры для государства в Haskell

StackOverflow https://stackoverflow.com/questions/3533745

Вопрос

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

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

Для того, чтобы привязать к 'st' и на самом деле вернуть значение, например,

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

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

Это было полезно?

Решение

Если вы посмотрите здесь, Вы увидите, что они определяют это так:

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

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

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top