#haskell #monads #record #applicative
#haskell #монады #запись #applicative
Вопрос:
Я пытаюсь определить экземпляры для Applicative и Monad из RWS, но должно быть что-то, чего мне не хватает. Например pure
, я получаю ошибку проверки. Это должно иметь какое-то отношение к тому факту, что я даю RWS f
в результате pure , несмотря на то, что f имеет тип a
. Я не понимаю, как получить доступ к другим аргументам RWS
(r, w и s) . Я был бы признателен, если бы кто-нибудь подробно объяснил некоторые понятия, такие как newtype
определение. Насколько я понимаю, мы определяем новый тип RWS
, который имеет 4 аргумента (r, w, s и a). Этот тип определяется с помощью constructor ( fromRWS
) , который что-то делает с аргументами. Поправьте меня, если я ошибаюсь. Если это правильно, RWS
определяется аргументами 4 или fromRWS
?
Двигаясь дальше, реализация for <*>
выдает ошибку типа. В нем говорится, что fromRWS2 применяется к слишком небольшому количеству аргументов. Однако я не вижу проблемы, поскольку я использовал тот же where
подход с предложением для решения аналогичной проблемы для переменной среды. Какие альтернативы я могу использовать?
При определении Monad
я только что получил parse error on input RWS
Пожалуйста, помогите мне определить экземпляры.
Вот мой код:
module RWS where
newtype RWS r w s a = RWS { fromRWS :: r -> s -> (a, s, w) }
instance Functor (RWS r w s) where
fmap f (RWS rws) = RWS $ r s -> let (a,s',w) = rws r s in (f a, s', w)
instance Monoid w => Applicative (RWS r w s) where
-- pure a -> RWS r w s a
pure f = RWS f
-- (<*>) :: RWS r w s (a -> b) -> RWS r w s a -> RWS r w s b
RWS f <*> RWS a = RWS fromRWS2
where fromRWS2 r1 s1 = f a
instance Monoid w => Monad (RWS r w s) where
--return :: a -> RWS r w s a
return x = RWS x
--(>>=) :: (RWS r w s a) -> (a -> (RWS r w s b)) -> (RWS r w s b)
RWS fr >>= f = f fr
Ответ №1:
Может быть, будет понятнее, если мы напишем RWS
как
newtype RWS r w s a = MakeRWS { fromRWS :: (r -> s -> (a, s, w)) }
Это определение дает вам три вещи:
- Конструктор типа
RWS
, принимающий четыреr w s a
аргумента. - Конструктор данных
MakeRWS
типа(r -> s -> (a, s, w)) -> RWS r w s a
- Средство доступа к полю
fromRWS
типаRWS r w s a -> (r -> s -> (a, s, w))
Как мы можем видеть, конструктор данных MakeRWS
должен быть применен к функции для построения значения типа RWS r w s a
.
В вашей pure
реализации вы применяете MakeRWS
значение типа a
, а не функцию. Это то, что идет не так с вашей чистой реализацией.
Как вы заметили в комментарии, тип pure
должен быть
a -> RWS r w s a
но ваша реализация имела бы этот тип, если бы она работала:
(r -> s -> (a, s, w)) -> RWS r w s a
Правильная реализация
pure a = MakeRWS (_r s -> (a, s, mempty)
Ваша реализация monad завершается с ошибкой синтаксического анализа, потому что у вас нет того же отступа в return
строке, что и в начале строки RWS
.
Комментарии:
1. Мне удалось исправить
pure
. Все еще возникают проблемы с<*>
and Monad после изменения отступов. Где я могу обновить код после внесения изменений? Разрешено ли это в исходном сообщении?2. изменения @andy_bruja не должны приводить к аннулированию ответа (ответов), поэтому, вероятно, не редактируйте его. 🙂
Ответ №2:
Просто следуйте типам. Мы можем сделать только так много с любой заданной вещью:
-- newtype RWS r w s a = RWS { fromRWS :: r -> s -> (a, s, w) }
-- .....
RWS tf <*> RWS ta = RWS tfa
where
tfa r1 s1 = (f a, s?, w2 ?? w3) -- what is ?
where -- what is ??
(f, s2, w2) = tf r1 s1
(a, s3, w3) = ta r1 s2
Аналогично для монады. Прежде всего return = pure
, и другой ответ показывает вам, как это определить:
pure a = RWS ta
where
ta _r s = (a, s, mempty)
Тогда привязка
--(>>=) :: (RWS r w s a) -> (a -> (RWS r w s b)) -> (RWS r w s b)
(RWS f) >>= k = RWS g
where
-- RWS f :: RWS r w s a
-- f :: r -> s -> (a, s, w)
-- RWS g :: RWS r w s b
-- g :: r -> s -> (b, s, w)
g r1 s1 = ??? -- what is ???
where
(a, s2, w2) = f r1 s1
(RWS h) = k a
-- RWS h :: RWS r w s b
-- h :: r -> s -> (b, s, w)
(b, s3, w3) = h r1 s???? -- what is ????