In Haskell, diese Art von Funktion zu überlasten (ad -Hoc-Polymorphismus) wird durch die Verwendung von Typklassen erreicht, nicht durch die Bindung des gleichen Namens unter mehreren Typen. Jetzt
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
class F a where f :: String -> a
instance F String where f = id
instance F Int where f = read
instance F Char where f = read
instance F Float where f = read
-- etc.
, f
kann auf jeder Art betrieben werden, für die eine Instanz von F
erklärt worden.
Leider kann man nicht mit dem folgenden weg:
instance Read a => F a where f = read
Vielleicht unintuitively, tut dies nicht eine Instanz von F
nur bei den Typen angeben, die eine Instanz von Read
haben. Da GHC Instanzen nur mit dem Kopf der Instanzdeklaration auflöst (der Teil rechts von =>
), deklariert dies tatsächlich alle Typen a
als Instanzen von F
, aber es macht einen Typfehler, um f
für alles aufzurufen, was nicht auch ist eine Instanz von Read
.
Es wird kompiliert, wenn Sie die UndecidableInstances
Erweiterung aktivieren, aber das führt nur zu anderen Problemen. Es ist ein Kaninchenloch, in das du dich nicht wirklich wagen willst.
Stattdessen sollten Sie eine Instanz F
für jeden einzelnen Typ deklarieren, den Sie mit f
bearbeiten möchten. Dies ist nicht sehr belastend für eine einfache Klasse wie diese, aber wenn Sie eine aktuelle Version von GHC verwenden, können Sie die folgende verwenden, um es etwas einfacher zu machen:
{-# LANGUAGE DefaultSignatures #-}
class F a where f :: String -> a
default f :: Read a => String -> a
f = read
nun für jede Art, die eine ist Instanz von Read
, können Sie seine Instanz von F
erklären, ohne dass die Durchführung der f
explizit bereitzustellen:
instance F Int
instance F Char
instance F Float
-- etc.
für alle Arten ohne Instanzen Read
, haben Sie immer noch eine explizite Implementierung fürschreiben.
Wenn Sie nur über die Leistung besorgt sind, sollten diese Dinge vom Compiler optimiert werden. – leftaroundabout
Ich bin nicht besorgt über die Leistung, ich möchte eine Version von 'lesen', die keine Anführungszeichen um Strings erfordert, aber funktioniert als normal' lesen' für alles andere. –
Die Frage http://stackoverflow.com/questions/9870962/haskell-making-a-superclass-of-num/ adressiert genau das gleiche Problem; einige Antworten dort können nützlich sein. –