Haskell Language
Des procurations
Recherche…
Utiliser un proxy
Le type Proxy :: k -> * , trouvé dans Data.Proxy , est utilisé lorsque vous avez besoin de donner des informations de type au compilateur - par exemple, pour choisir une instance de classe de type - qui est néanmoins sans importance à l'exécution.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Les fonctions qui utilisent un Proxy utilisent généralement ScopedTypeVariables pour choisir une instance de classe de type basée sur a type.
Par exemple, l'exemple classique d'une fonction ambiguë,
showread :: String -> String
showread = show . read
ce qui se traduit par une erreur de type car le constructeur ne sait pas quelle instance de Show ou de Read à utiliser, peut être résolue avec Proxy :
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
Lorsque vous appelez une fonction avec Proxy , vous devez utiliser une annotation de type pour déclarer celle a vous vouliez dire.
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
L'idiome "proxy polymorphe"
Étant donné que le Proxy ne contient aucune information d'exécution, il n'est jamais nécessaire de faire correspondre le modèle au constructeur du Proxy . Un idiome commun consiste donc à faire un résumé sur le type de données Proxy utilisant une variable de type.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Maintenant, si vous avez une fa dans la portée de certains f , vous n'avez pas besoin d'écrire Proxy :: Proxy a lorsque vous appelez f .
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Le proxy est comme ()
Comme Proxy ne contient aucune information d'exécution, vous pouvez toujours écrire une transformation naturelle fa -> Proxy a pour tout f .
proxy :: f a -> Proxy a
proxy _ = Proxy
C'est comme si une valeur donnée pouvait toujours être effacée sur () :
unit :: a -> ()
unit _ = ()
Techniquement, Proxy est l'objet terminal dans la catégorie des foncteurs, tout comme () est l'objet terminal dans la catégorie des valeurs.