Ich versuche, meinen eigenen Datentyp zu erstellen, der Teil der Monad-Klasse sein wird, aber
newtype Container a = Container a deriving Monad
gibt mir diesen Fehler:
* 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
Es funktioniert gut für andere Klassen (z. B. Show), aber nicht für Monad. Wie kann ich ghci davon überzeugen, meine Container to Monad-Klasse zu instanziieren?
Vielen Dank
a
es sich nicht um eine Monade handelt, daher macht es nicht viel Sinn. Wenn Sie zum Beispiel verwenden würden, wirdnewtype Container a = Container [a] deriving (Functor, Applicative, Monad)
es funktionieren, da[]
es sich um eine Instanz von handeltMonad
.GenerlizedNewtypeDeriving
dient speziell zum "Anheben" der Instanzen des umschlossenen Typs auf den neuen Typ. Die Frage, wie (oder ob) man automatisch eineMonad
Instanz ableiten kann,Container
ist immer noch interessant. (Die Tatsache, dassbase
dieMonad
InstanzIdentity
explizit definiert wird, deutet darauf hin, dass dies nicht möglich ist.)Monad
gehört nicht zu den Typklassen, die der Haskell-Standard zur automatischen Ableitung bereitstellt (Show
zusammen mit einigen anderen grundlegenden). GHC kann es allerdings mit den richtigen Erweiterungen tun, glaube ich.GeneralizedNewtypeDeriving
, dass sie aktiviert ist, und eine Frage ist, warum sie immer noch nicht funktioniert.Antworten:
Nur ein fester Satz von Standardklassen unterstützt das sofortige Ableiten:
Insbesondere
Monad
gehört weder zu dieser noch zu der erweiterten Liste.Es gibt weitere Erweiterungen, die das Ableiten auf beliebige Klassen verallgemeinern, die jedoch nicht zu 100% automatisiert werden können. Jemand muss irgendwo angeben, wie diese Ableitung erfolgen soll; Je nach Klasse muss der Benutzer möglicherweise die Last tragen, da Informationen vorliegen, auf die grundsätzlich nicht geschlossen werden kann.
In Ihrem Fall entspricht der Newtype
Container
repräsentativ derIdentity
Monade in der Standardbibliothek, sodass Sie Folgendes verwenden könnenDerivingVia
:In dieser speziellen Situation gibt es nur eine sinnvolle Instanz, aber meistens ist es nicht einfach zu sagen, wie die Instanz aussehen soll, selbst wenn es nur eine gibt.
quelle
Functor
undApplicative
, aber dann den Typ vonContainer 3 >>= (+1)
mit vergleichenIdentity 3 >>= (+1)
. Ich weiß nicht, ob das damit zusammenhängtDerivingVia
oder nicht.Container 3 >>= (+ 1) :: Num (Container b) => Container b
undIdentity 3 >>= (+ 1) :: Num b => Identity b
. Ich bin mir nicht sicher, warumContainer b
, anstattb
dieNum
Einschränkung zu haben.)(+ 1) :: Num c => c -> c
betrifft(+ 1) :: a -> Container b
, müssen Sie sich vereinen , um einen Kleisli-Pfeil zu habenc ~ Container b
. Aber ich bin mir nicht sicher, womit Sie anfangen sollen.Identity
die nicht definiert istContainer
, alsIdentity 3 >>= (+1)
auswertet zuIdentity 4
.instance Num a => Num (Identity a)
definierte gibt.