MonadFix экземпляр для Put
Надеюсь, простой вопрос: binary
пакет определяет два типа, Get
а также Put
, Первый по сути является государственной монадой, а второй по сути является писателем. И государство, и писатель имеют разумное MonadFix
экземпляры, так что я ожидаю, что Get
а также Put
также будет.
Get
делает. Put
не делает. Итак, возможно ли определить соответствующий MonadFix
экземпляр для Put
(действительно для PutM
)?
Более общий вопрос: как обычно проверить, что экземпляр класса типов действительно удовлетворяет законам этого класса типов?
2 ответа
Как видно из исходного кода для двоичного пакета ( Data.Binary.Put: 71), структура данных, используемая для монадических значений, является строгой в компоновщике. Поскольку извлечение значения из монады должно вызвать структуру, в которой это значение найдено, это приведет к бесконечному циклу, если построитель зависит от ввода.
data PairS a = PairS a !Builder
newtype PutM a = Put { unPut :: PairS a }
Так что вы могли бы написать MonadFix
например, но вы не сможете сделать что-нибудь полезное с этим. Но я не думаю, что вы могли бы сделать что-нибудь полезное с MonadFix
здесь, во всяком случае, по крайней мере, ничего, что вы не могли бы сделать с простой старой fix
, так как PutM
монада в основном Writer Builder
(но со специализированной реализацией).
Что касается вашего второго вопроса, он не связан с первым, поэтому вы должны задать его как отдельный вопрос.
Вот ответ на ваш второй вопрос и продолжение комментария Дэниела. Вы проверяете законы вручную, а я буду использовать пример Functor
законы для Maybe
:
-- First law
fmap id = id
-- Proof
fmap id
= \x -> case x of
Nothing -> Nothing
Just a -> Just (id a)
= \x -> case x of
Nothing -> Nothing
Just a -> Just a
= \x -> case x of
Nothing -> x
Just a -> x
= \x -> case x of
_ -> x
= \x -> x
= id
-- Second law
fmap f . fmap g = fmap (f . g)
-- Proof
fmap f . fmap g
= \x -> fmap f (fmap g x)
= \x -> fmap f (case x of
Nothing -> Nothing
Just a -> Just (f a) )
= \x -> case x of
Nothing -> fmap f Nothing
Just a -> fmap f (Just (g a))
= \x -> case x of
Nothing -> Nothing
Just a -> Just (f (g a))
= \x -> case x of
Nothing -> Nothing
Just a -> Just ((f . g) a)
= \x -> case x of
Nothing -> fmap (f . g) Nothing
Just a -> fmap (f . g) (Just a)
= \x -> fmap (f . g) (case x of
Nothing -> Nothing
Just a -> Just a )
= \x -> fmap (f . g) (case x of
Nothing -> x
Just a -> x )
= \x -> fmap (f . g) (case x of
_ -> x )
= \x -> fmap (f . g) x
= fmap (f . g)
Очевидно, я мог бы пропустить многие из этих шагов, но я просто хотел изложить полное доказательство. Доказать такие законы сначала сложно, пока вы не овладеете ими, поэтому лучше начать медленно и педантично, а затем, когда вы поправитесь, вы можете начать комбинировать шаги и даже делать некоторые из них через некоторое время для более простых из них.