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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow