2014-01-19 4 views
6

Meine Frage bezieht sich auf eine andere Frage auf die Antwort: https://stackoverflow.com/a/11766789/3212958Wird <- implizit Typen in einem Haskell-Block blockiert?

In seiner Antwort ertes schreibt die folgende Art Signatur

select :: [a] -> [(a, [a])] 

Wenn jedoch select tatsächlich verwendet wird, ertes schreibt das folgende innerhalb eines do Block

(y, ys) <- select xs 

Bitte helfen Sie mir etwas Licht auf, wie das Tupel (y, ys) entspricht den Rückgabetyp wählen, Namen ly [(a, [a])]. Verändert Haskell die Typen irgendwann? (Hat Haskell jemals Arten zu erzwingen?) Ist <- ein Tupel des Typs aus der Liste Monade extrahieren, die select zurückgibt?

Danke, Max

--- EDIT: ---

@Lee newbs bevor Sie versuchen, über Typen desugar erinnert an die Vernunft. Nachdem Sie >>= explizit gemacht haben, ist es klarer, was vor sich geht. Nach Entzuckern, sucht die Funktion in Frage wie:

select xs >>= \(y, ys) -> fmap (y:) (perms (n - 1) ys) 

Und für Listen, xs >>= f = concat (map f xs). So ein besserer Messwert von (y, ys) in diesem Zusammenhang ist als die Signatur der Funktion, um über die Liste abzubilden.

+3

'select' gibt eine Liste zurück. Wenn Sie 'a > = func'. Bind für Listen ist wie folgt definiert: 'm >> = f = concat (map f m)', also schreiben Sie 'map func (select xs)'. Es gibt keine Art Zwang in Haskell. – user2407038

+0

@ user2407038 einige geringfügige Technik hier; 'a' ist nicht 'jedes Element',' a' repräsentiert * ein * (beliebiges aber spezifisches) Element der Liste. –

Antwort

13

In do Notation,

do x1 <- action1 
    action2 

in action1 >>= \x1 -> action2 übersetzt

Das bedeutet, dass, wenn action1m a für einige Monade hat Typ m, dann hat x1a geben. Es ist nicht wirklich zwingende Typen, sondern "Entpacken" Sie den Wert aus der monadischen Aktion action1 und binden Sie es an x1.

4

(y, ys) ist vom Typ (b, c)

Der Rückgabetyp select vom Typ [(a, [a])]

In <- die Typen sind eigentlich d und Monad m => m d. So können wir die folgenden Typengleichheiten schreiben:

(b, c) ~ d 
[(a, [a])] ~ Monad m => m d 

Lösung ist einfach.Erster Ersatz d aus der ersten Gleichung in die zweite Gleichung:

[(a, [a])] ~ Monad m => m (b, c) 

Jetzt zu sehen, was los ist ich ein Präfix Form von [] Typkonstruktor verwenden (es ist nicht gültig Haskell, aber Sie sollten auf die Idee kommen):

[] (a, [a]) ~ Monad m => m (b, c) 

So

m ~ [] 
(a, [a]) ~ (b, c) 

An diesem Punkt der Compiler überprüft, ob instance Monad [a] existiert. Der Rest ist einfach:

a ~ b 
[a] ~ c 
+1

'[] (a, [] a)' ist tatsächlich gültig Haskell, oder sogar '[] ((,) a ([] a))' wenn Sie möchten. –

+0

Oh, ich wusste nicht, dass der Typkonstruktor für '[]' auf diese Weise verwendet werden kann, genau wie der Wertkonstruktor. – nponeccop

+0

Ja, ich war angenehm überrascht, es auch zu lernen. Sicher macht es einfacher, die Listenmonade zu erklären. –

Verwandte Themen