Haskell Language
Proxy
Ricerca…
Utilizzo del proxy
Il tipo Proxy :: k -> *
, che si trova in Data.Proxy
, viene utilizzato quando è necessario fornire al compilatore alcune informazioni sul tipo, ad esempio per selezionare un'istanza di classe di tipo, che tuttavia è irrilevante in fase di runtime.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Funzioni che utilizzano un Proxy
genere utilizzano ScopedTypeVariables
scegliere un'istanza del tipo classe basata sulla a
tipo.
Ad esempio, il classico esempio di una funzione ambigua,
showread :: String -> String
showread = show . read
che si traduce in un errore di tipo perché l'elaboratore non sa quale istanza di Show
o Read
da usare, può essere risolto usando il Proxy
:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
Quando si chiama una funzione con Proxy
, è necessario utilizzare un tipo di annotazione per dichiarare che a
volevi dire.
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
L'idioma "proxy polimorfico"
Poiché il Proxy
non contiene informazioni sul runtime, non è mai necessario associare il modello al costruttore del Proxy
. Quindi un idioma comune è quello di astrarre il tipo di dati Proxy
usando una variabile di tipo.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Ora, se ti capita di avere un fa
in scope per qualche f
, non devi scrivere Proxy :: Proxy a
quando chiami f
.
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Proxy è come ()
Poiché Proxy
non contiene informazioni di runtime, puoi sempre scrivere una trasformazione naturale fa -> Proxy a
per qualsiasi f
.
proxy :: f a -> Proxy a
proxy _ = Proxy
Questo è esattamente come qualsiasi valore dato può sempre essere cancellato a ()
:
unit :: a -> ()
unit _ = ()
Tecnicamente, Proxy
è l'oggetto terminale nella categoria dei funtori, proprio come ()
è l'oggetto terminale nella categoria di valori.