Haskell Language

Proxies

Using Proxy

The Proxy :: k -> * type, found in Data.Proxy, is used when you need to give the compiler some type information - eg, to pick a type class instance - which is nonetheless irrelevant at runtime.

{-# LANGUAGE PolyKinds #-}

data Proxy a = Proxy

Functions which use a Proxy typically use ScopedTypeVariables to pick a type class instance based on the a type.

For example, the classic example of an ambiguous function,

showread :: String -> String
showread = show . read

which results in a type error because the elaborator doesn’t know which instance of Show or Read to use, can be resolved using Proxy:

{-# LANGUAGE ScopedTypeVariables #-}

import Data.Proxy

showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read

When calling a function with Proxy, you need to use a type annotation to declare which a you meant.

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

The “polymorphic proxy” idiom

Since Proxy contains no runtime information, there is never a need to pattern-match on the Proxy constructor. So a common idiom is to abstract over the Proxy datatype using a type variable.

showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read

Now, if you happen to have an f a in scope for some f, you don’t need to write out Proxy :: Proxy a when calling f.

ghci> let chars = "foo"  -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"

Proxy is like ()

Since Proxy contains no runtime information, you can always write a natural transformation f a -> Proxy a for any f.

proxy :: f a -> Proxy a
proxy _ = Proxy

This is just like how any given value can always be erased to ():

unit :: a -> ()
unit _ = ()

Technically, Proxy is the terminal object in the category of functors, just like () is the terminal object in the category of values.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow