Haskell Language
Ombud
Sök…
Med hjälp av proxy
Proxy :: k -> *
-typen, som finns i Data.Proxy
, används när du behöver ge kompilatorn viss typinformation - till exempel att välja en typklassinstans - som inte desto mindre är irrelevant vid körning.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Funktioner som använder en Proxy
använder vanligtvis ScopedTypeVariables
att välja en typklassinstans baserad på a
typen.
Till exempel det klassiska exemplet på en tvetydig funktion,
showread :: String -> String
showread = show . read
vilket resulterar i ett typfel eftersom elaboratoren inte vet vilken instans av Show
eller Read
att använda, kan lösas med Proxy
:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
När du ringer till en funktion med Proxy
måste du använda en typanteckning för att förklara vilken a
du menade.
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
Det "polymorfa proxy" -språket
Eftersom Proxy
innehåller någon runtime-information finns det aldrig något behov av att matcha mönster på Proxy
konstruktören. Så ett vanligt formspråk är att abstrahera över Proxy
datatypen med en typvariabel.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Nu, om du råkar ha en fa
i räckvidd för vissa f
, behöver du inte skriva ut Proxy :: Proxy a
när du ringer f
.
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Proxy är som ()
Eftersom Proxy
innehåller information om runtime, kan du alltid skriva en naturlig transformation fa -> Proxy a
för alla f
.
proxy :: f a -> Proxy a
proxy _ = Proxy
Detta är precis som hur ett givet värde alltid kan raderas till ()
:
unit :: a -> ()
unit _ = ()
Tekniskt sett är Proxy
terminalobjektet i kategorin funktorer, precis som ()
är terminalobjektet i kategorin värden.