Haskell Language
Proxy
Szukaj…
Korzystanie z serwera proxy
Typ Proxy :: k -> *
, znajdujący się w Data.Proxy
, jest używany, gdy trzeba podać kompilatorowi jakieś informacje o typie - np. Data.Proxy
instancję klasy typu - co jednak nie ma znaczenia w czasie wykonywania.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Funkcje, które używają Proxy
zazwyczaj korzystają ScopedTypeVariables
wybrać instancję klasy w oparciu o typ a
typem.
Na przykład klasyczny przykład niejednoznacznej funkcji,
showread :: String -> String
showread = show . read
co powoduje błąd typu, ponieważ twórca nie wie, która instancja Show
lub Read
do użycia, można rozwiązać za pomocą Proxy
:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
Przy wywołaniu funkcji z Proxy
, trzeba użyć typu adnotacji zadeklarować które chodziło. a
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
Idiom „polimorficzne proxy”
Ponieważ Proxy
nie zawiera informacji o środowisku wykonawczym, nigdy nie ma potrzeby dopasowywania wzorców w konstruktorze Proxy
. Dlatego powszechnym idiomem jest abstrakty na typie danych Proxy
za pomocą zmiennej typu.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Teraz, jeśli akurat masz fa
w zakresie dla jakiegoś f
, nie musisz wypisywać Proxy :: Proxy a
podczas wywoływania f
.
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Proxy jest jak ()
Ponieważ Proxy
nie zawiera informacji o środowisku wykonawczym, zawsze możesz napisać naturalną transformację fa -> Proxy a
dla dowolnego f
.
proxy :: f a -> Proxy a
proxy _ = Proxy
Jest to tak, jak zawsze można usunąć dowolną wartość do ()
:
unit :: a -> ()
unit _ = ()
Technicznie rzecz biorąc, Proxy
jest obiektem końcowym w kategorii funktorów, podobnie jak ()
jest obiektem końcowym w kategorii wartości.