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)

Очевидно, я мог бы пропустить многие из этих шагов, но я просто хотел изложить полное доказательство. Доказать такие законы сначала сложно, пока вы не овладеете ими, поэтому лучше начать медленно и педантично, а затем, когда вы поправитесь, вы можете начать комбинировать шаги и даже делать некоторые из них через некоторое время для более простых из них.

Другие вопросы по тегам