Haskell - Automati c Экземпляр монады - PullRequest
8 голосов
/ 28 февраля 2020

Я пытаюсь создать свой собственный тип данных, который будет частью класса Monad, но

newtype Container a = Container a deriving Monad

выдает мне эту ошибку:

   * Can't make a derived instance of `Monad Container'
        (even with cunning GeneralizedNewtypeDeriving):
        cannot eta-reduce the representation type enough
    * In the newtype declaration for `Container'
   |
30 | newtype Container a = Container a deriving Monad

Работает нормально для другие классы (показать, например), но не для Monad, так как я могу убедить ghci создать экземпляр моего класса Container to Monad?

Спасибо

1 Ответ

9 голосов
/ 28 февраля 2020

Отлично работает для других классов (показать, например)

Только фиксированный набор стандартных классов поддерживает получение из коробки:

В Haskell 98 единственными производными классами являются Eq, Ord, Enum, Ix, Bounded, Read и Show. Различные расширения языка расширяют этот список.

--- Руководство пользователя GH C

В частности Monad не принадлежит этому списку, ни расширенный.

Есть больше расширений, которые обобщают порождение для произвольных классов, но они не могут быть на 100% автоматизированы. Кто-то где-то должен указать, как это происходит; в зависимости от класса, пользователь может быть обязан нести бремя, потому что есть информация, которая принципиально не может быть выведена.

В вашем случае новый тип Container репрезентативно эквивалентен монаде Identity в стандартная библиотека, поэтому вы можете использовать DerivingVia:

{-# LANGUAGE DerivingVia #-}
import Data.Functor.Identity

newtype Container a = Container a deriving (Functor, Applicative, Monad) via Identity

В этой конкретной ситуации существует только один разумный экземпляр, но в большинстве случаев непросто определить, каким должен быть этот экземпляр, даже если только один.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...