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.