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.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow