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.