Поиск…


Использование прокси

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



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow