Haskell Language
Proxies
Suche…
Proxy verwenden
Der in Data.Proxy
findende Typ Proxy :: k -> *
wird verwendet, wenn Sie dem Compiler einige Data.Proxy
geben müssen, z. B. zur Auswahl einer Typklasseninstanz, die jedoch zur Laufzeit nicht relevant ist.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Funktionen, die einen Proxy
normalerweise ScopedTypeVariables
, um eine Typklasseninstanz basierend auf a
Typ auszuwählen.
Zum Beispiel das klassische Beispiel einer mehrdeutigen Funktion,
showread :: String -> String
showread = show . read
was zu einem Typfehler führt, weil der Ausführende nicht weiß, welche Instanz von Show
oder Read
verwendet werden soll, kann mit Proxy
aufgelöst werden:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
Wenn eine Funktion mit Aufruf Proxy
, müssen Sie eine Typanmerkung verwenden , um zu erklären , was a
Sie gemeint.
ghci> showread (Proxy :: Proxy Int) "3"
"3"
ghci> showread (Proxy :: Proxy Bool) "'m'" -- attempt to parse a char literal as a Bool
"*** Exception: Prelude.read: no parse
Das "polymorphe Proxy" - Idiom
Da Proxy
keine Laufzeitinformationen enthält, ist es im Proxy
Konstruktor nie erforderlich, ein Muster zu finden. Daher ist es üblich, den Proxy
Datentyp mit einer Typvariablen zu abstrahieren.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Wenn Sie nun ein fa
im Gültigkeitsbereich von f
, müssen Sie Proxy :: Proxy a
nicht Proxy :: Proxy a
wenn Sie f
aufrufen.
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Proxy ist wie ()
Da Proxy
keine Laufzeitinformationen enthält, können Sie immer eine natürliche Transformation fa -> Proxy a
für jedes f
schreiben.
proxy :: f a -> Proxy a
proxy _ = Proxy
Dies ist genau so, wie ein beliebiger Wert immer in ()
gelöscht werden kann:
unit :: a -> ()
unit _ = ()
Technisch gesehen ist Proxy
das Terminalobjekt in der Kategorie von Funktoren, genau wie ()
das Terminalobjekt in der Wertkategorie.