Как определить экземпляры Applicative и Monad при работе с конструктором, определенным с использованием синтаксиса записи

#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 ????