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
- это конечный объект в категории функторов, так же как ()
- это конечный объект в категории значений.