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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow