Ich werde mit der Einführung eines konkreten Problems (StackOverflow Jungs wie folgt) beginnen. Sagen Sie bitte einen einfachen Typ definierenWarum werden Instanzen nur von ihren Köpfen abgeglichen?
data T a = T a
Dieser Typ ist ein Functor
, Applicative
und ein Monad
. Ignorieren automatische Ableitung, um diese Instanzen zu bekommen, müssen Sie jede von ihnen zu schreiben, auch wenn Applicative
bedeutet Functor
. Mehr als das, könnte ich eine ziemlich starke Bedingung definiert eine Klasse wie diese
class Wrapper f where
wrap :: a -> f a
unwrap :: f a -> a
Dies ist und es bedeutet, auf jeden Fall Monad
, aber ich kann
instance Wrapper f => Monad f where
return = wrap
fa >>= f = f $ unwrap fa
weil dies nicht schreiben, aus irgendeinem Grunde bedeutet "alles ist ein Monad
(alle f
), nur wenn es ein Wrapper
ist", anstatt "alles das ist ein Wrapper
ist ein Monad
".
Ebenso können Sie die Monad a => Applicative a
und Applicative a => Functor a
Instanzen nicht definieren.
Eine andere Sache, die Sie nicht tun können (die nur wahrscheinlich verwandt ist, weiß ich wirklich nicht) ist eine Klasse eine Oberklasse von einer anderen Klasse zu sein und eine Standardimplementierung der Unterklasse bereitzustellen. Sicher, es ist großartig, dass class Applicative a => Monad a
, aber es ist viel weniger groß, dass ich noch dieInstanz definieren muss, bevor ich die Monad
eine definieren kann.
Dies ist keine Tirade. Ich habe viel geschrieben, weil sonst das schnell als "zu breit" oder "unklar" markiert würde. Die Frage läuft auf den Titel hinaus. Ich weiß (zumindest bin ich mir ziemlich sicher), dass es einen theoretischen Grund dafür gibt, also frage ich mich, was genau die Vorteile hier sind.
Als eine Unterfrage möchte ich fragen, ob es praktikable Alternativen gibt, die immer noch alle (oder die meisten) dieser Vorteile behalten, aber erlauben, was ich geschrieben habe.
Zusatz: Ich vermute, eine der Antworten könnte etwas entlang der Linien sein „Was ist, wenn mein Typ ein Wrapper
ist, aber ich will nicht die Monad
Instanz verwenden, dass das bedeutet?“. Dazu frage ich, warum konnte der Compiler nicht einfach den spezifischsten auswählen? Wenn es einen instance Monad MyType
gibt, ist es sicherlich spezifischer als instance Wrapper a => Monad a
.
'unwrap' beschreibt ein Verhalten, das keine' Monad'-Methoden implementieren; Wenn das nicht der Fall wäre, würde 'unwrap' erlauben, ein' a' aus einer 'IO a'-Berechnung zu extrahieren (wie 'unsafePerformIO'), was den Zweck einer' IO'-Monade im ersten Fall zunichte machen würde Ort. Eine Klasse kann nur weniger mächtig/expressiv sein als ihre Unterklassen. – Jubobs
Was wird "unwrap" für "Nothing" definieren, wenn die Instanz für "Maybe" definiert wird? – Sibi
@Sibi Einfach, es gibt keine Instanz für Maybe. Ich glaube nicht, dass er behauptet hat, dass es da war. Außerdem bezweifle ich, dass Wrapper Monad ohne irgendwelche Gesetze (außer den freien) darauf deutet. – Cubic