Haskell Language
Proxies
Buscar..
Usando Proxy
El tipo Proxy :: k -> *
, que se encuentra en Data.Proxy
, se usa cuando se necesita dar cierta información de tipo al compilador, por ejemplo, para elegir una instancia de clase de tipo, que no obstante es irrelevante en el tiempo de ejecución.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Las funciones que usan un Proxy
generalmente usan ScopedTypeVariables
para elegir una instancia de clase de tipo basada en a
tipo.
Por ejemplo, el ejemplo clásico de una función ambigua,
showread :: String -> String
showread = show . read
lo que resulta en un error de tipo porque el elaborador no sabe qué instancia de Show
o Read
usar, puede resolverse usando un Proxy
:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
Cuando se llama a una función con Proxy
, es necesario utilizar una anotación de tipo para declarar la cual a
que quería decir.
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
El lenguaje "proxy polimórfico"
Dado que el Proxy
no contiene información de tiempo de ejecución, nunca es necesario realizar una coincidencia de patrones en el constructor Proxy
. Por lo tanto, un lenguaje común es abstraer sobre el tipo de datos Proxy
usando una variable de tipo.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Ahora, si tiene un fa
en el alcance de alguna f
, no necesita escribir Proxy :: Proxy a
cuando llame a f
.
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Proxy es como ()
Dado que Proxy
no contiene información de tiempo de ejecución, siempre puede escribir una transformación natural fa -> Proxy a
para cualquier f
.
proxy :: f a -> Proxy a
proxy _ = Proxy
Esto es así como cualquier valor dado siempre puede borrarse a ()
:
unit :: a -> ()
unit _ = ()
Técnicamente, Proxy
es el objeto terminal en la categoría de los funtores, al igual que ()
es el objeto terminal en la categoría de valores.