Haskell Language
Доверенные
Поиск…
Использование прокси
Тип Proxy :: k -> * , найденный в Data.Proxy , используется, когда вам нужно предоставить компилятору некоторую информацию о типе - например, выбрать экземпляр класса типа, который, тем не менее, не имеет значения во время выполнения.
{-# LANGUAGE PolyKinds #-}
data Proxy a = Proxy
Функции , которые используют Proxy - ScopedTypeVariables a Proxy обычно используют ScopedTypeVariables , чтобы выбрать экземпляр класса типа на основе a типа.
Например, классический пример неоднозначной функции,
showread :: String -> String
showread = show . read
что приводит к ошибке типа, поскольку разработчик не знает, какой экземпляр Show или Read использовать, может быть разрешен с помощью Proxy :
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Proxy
showread :: forall a. (Show a, Read a) => Proxy a -> String -> String
showread _ = (show :: a -> String) . read
При вызове функции с Proxy , вам нужно использовать аннотацию типа , чтобы объявить , какие вы имели в виду. 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
Идиома «полиморфный прокси»
Поскольку Proxy содержит информации о времени выполнения, никогда не нужно сопоставлять шаблоны в конструкторе Proxy . Таким образом, общая идиома заключается в абстрактном Proxy типа Proxy с использованием переменной типа.
showread :: forall proxy a. (Show a, Read a) => proxy a -> String -> String
showread _ = (show :: a -> String) . read
Теперь, если у вас есть fa в области для некоторого f , вам не нужно выписывать Proxy :: Proxy a при вызове f .
ghci> let chars = "foo" -- chars :: [Char]
ghci> showread chars "'a'"
"'a'"
Прокси - это как ()
Поскольку Proxy содержит информации о времени выполнения, вы всегда можете написать естественное преобразование fa -> Proxy a для любого f .
proxy :: f a -> Proxy a
proxy _ = Proxy
Это похоже на то, как любое значение всегда можно стереть до () :
unit :: a -> ()
unit _ = ()
Технически, Proxy - это конечный объект в категории функторов, так же как () - это конечный объект в категории значений.