Wie ist IO eine Monade?

7

Ich lerne die Programmiersprache Haskell. Nach dem, was ich lese, stellt Input / Ouput ( IO ) die Reinheit von Haskell vor Herausforderungen, da wir per Definition mit der Außenwelt interagieren. Aus Wikipedia:

In einer rein funktionalen Sprache wie Haskell können Funktionen im Rahmen der Funktionssemantik keine äußerlich sichtbaren Nebenwirkungen haben. Obwohl eine Funktion keine Nebenwirkung direkt verursachen kann, kann sie einen Wert erstellen, der eine gewünschte Nebenwirkung beschreibt, die der Aufrufer zu einem geeigneten Zeitpunkt anwenden sollte.

In der Haskell-Notation stellt ein Wert vom Typ IO a eine Aktion dar, die bei Ausführung einen Wert vom Typ a erzeugt.

Bald erfuhr ich, dass IO ein Beispiel für eine Haskell-Monade ist. Obwohl wir nicht viele Erklärungen bekommen, was Monaden sind. Von Functors, Applicatives und Monaden in Bildern

So lernen Sie Monaden kennen:

  1. Promotion in Informatik.
  2. Wirf es weg, weil du es für diesen Abschnitt nicht brauchst!

Inzwischen habe ich verschiedene Definitionen von gelesen - dass sie Kontext hinzufügen oder kleinere Programmiersprachen innerhalb einer großen um ein bestimmtes Konzept erstellen. Ich versuche immer noch ein Gefühl dafür zu bekommen, welche Monaden und wie diese Ideen angewendet werden.

In Haskell gibt monades eine andere Typklasse, die im Grunde nur von einer Regel definiert wird. Und IOist ein Beispiel dafür.

class Monad m where    
    (>>=) :: m a -> (a -> m b) -> m b  

/programming/44965/what-is-a-monad

Ist hier etwas Algebraisches los? Was ist so algebraisch an IO?


Ich entschuldige mich dafür, dass ich sprachspezifisch bin. Ich hoffe, dass der größte Teil dieser Diskussion für alle funktionalen Programmiersprachen gilt. Alle Fehler in meiner Diskussion stellen mein eigenes begrenztes Verständnis dieses Bereichs dar.

Es gibt eine andere Definition von Monade, die ich in nLab gefunden habe und die nicht einmal spezifisch für Programmiersprachen ist.

In einer separaten Frage möchte ich verstehen, wie der kategorietheoretische Begriff der Monade mit der CS-Definition im Fall von Haskell übereinstimmt.

John Mangual
quelle

Antworten:

9

TLDR: Haskell Typen und Funktionen bilden eine Kategorie und aus , dass wir feststellen , dass die Dinge mit >>=und returndie Regeln für die Monaden erfüllen.

Um zu überlegen, was es für einen Typ bedeutet, Teil eines Monadentripletts zu sein, müssen wir zunächst überlegen, was eine Kategorie im Sinne von Haskell bedeutet.

Wir lassen unsere Kategorie Haskmit Objekten als Haskell-Typen definieren und Pfeile als Funktionen. Jeder Identitätspfeil ist eine Instanz von idund die Zusammensetzung ist normal .. Es ist trivial zu sehen, dass diese die normalen Kohärenzbedingungen erfüllen.

Wir können uns jetzt Endofunktoren in Hask ansehen. Sie enthalten zwei Teile, eine Zuordnung von Typ zu Typ und eine Zuordnung von Funktionen zu Funktionen

  • map g . map f = map (g . f)
  • map id = id

Funktoren sind daher Typkonstruktoren (die Typen Typen zuordnen), die mit einer Funktion gepaart sind, mapdie Pfeile a -> bzu Pfeilen hebt F a -> F b. Wir können natürliche Transformationen zwischen ihnen auch als etwas definieren, das ein Mitglied F azu einem Mitglied "gleitet" G a, das die normalen Kohärenzbedingungen erfüllt

  • nat . fmap f = fmap f . nat

Wir können also schließen, dass eine natürliche Transformation etwas mit dem Typ ist

nat :: forall a. F a -> G a

Schließlich nehmen wir zur Kenntnis, dass der Identitätstyp Konstruktor

type Id a = a

ist ein Funktor, dessen Karte durch Identität gegeben ist.

Wir sind jetzt bereit, über Monaden zu diskutieren! Eine Monade ist ein Triplett von 3 Dingen,

  • Ein Funktor, F
  • Eine natürliche Transformation returnzwischen IdundF
  • Eine natürliche Transformation joinzwischen F x FundF

Mit den Kohärenzbedingungen, die join . fmap join = join . joinund join . fmap return = join . return = id.

wobei das xProdukt das Produkt zweier Funktoren ist, das nur durch die Zusammensetzung der Typkonstruktoren definiert wird.

Die IOMonade hat ein . Das ist unsere erste natürliche Transformation. Unsere zweite ist nicht ganz so einfach, aber wir können definieren alsreturn :: a -> IO a Id a -> IO ajoin

join :: IO (IO a) -> IO a
join = (>>= id)

Wir können joinals Sequenzierungsoperation betrachten. Es nimmt alle Aktionen auf, die in der Struktur des Äußeren gespeichert sind, IOund klebt sie vor alle Aktionen im Inneren IO, wodurch eine größere, aber flache zurückgegeben wird IO a.

Im Wesentlichen haben wir diesen abstrakten Begriff von Monaden in der Kategorietheorie, und da Haskell-Typen als Kategorie angesehen werden können, können wir normale kategorietheoretische Begriffe wie Monaden anwenden und gemeinsame Muster daraus ziehen. Das ist es. Es gibt keinen geheimen Kategorietheorie-Saft, der Monaden über diese Kohärenzbedingungen hinaus eine höhere Bedeutung verleiht.

Dies ist eigentlich ein weit verbreitetes Muster. Wann immer wir etwas mit Kategorien betrachten, sei es Logik, Semantik oder Typensysteme, können wir die letzten 100 Jahre der Forschung blind auf unsere neue Kategorie anwenden und "neue" Abstraktionen entdecken.

Daniel Gratzer
quelle