サーチ…


プロキシの使用

Data.ProxyにあるProxy :: k -> *型は、コンパイラにいくつかの型情報を渡す必要があるとき(たとえば、型クラスインスタンスを選択するときなど)に使用されますが、それは実行時には関係ありません。

{-# LANGUAGE PolyKinds #-}

data Proxy a = Proxy

Proxyを使用する関数は通常、 ScopedTypeVariablesを使用してa型に基づいて型クラスインスタンスを選択します。

例えば、あいまいな関数の古典的な例は、

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

エラボレータがShowまたはReadインスタンスを使用するか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データ型を抽象化することです。

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

さて、あるfスコープにfaがあると、 f呼び出すときにProxy :: Proxy aを書く必要はありません。

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

プロキシはlikeです()

Proxyにはランタイム情報が含まれていないので、任意のf自然な変換fa -> Proxy aを書くことができます。

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