这是一个取自Reflection-0.5的最小例子。
{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
{-# OPTIONS_GHC -fno-cse -fno-full-laziness -fno-float-in #-}
import Control.Applicative
import Data.Proxy
newtype Zero = Zero Zero deriving (Show)
class ReifiesNum s where
reflectNum :: Num a => proxy s -> a
instance ReifiesNum Zero where
reflectNum = pure 0
在GHCi中,我得到以下内容:
>:t Zero
Zero :: Zero -> Zero
这是有道理的:我要求构造函数的类型取零并返回零。
>:t reflectNum
reflectNum :: (ReifiesNum s, Num a) => proxy s -> a
我可以编写类似
的内容>let x = Just (undefined::Zero)
>reflectNum x
因为类型Just Zero匹配类型变量'proxy s'。
最后,令人困惑的部分:
>:t (reflectNum Zero)
(reflectNum Zero) :: Num a => a
我不明白构造函数的类型Zero :: Zero - > Zero显然与类型变量'proxy s'匹配,但显然它确实是因为(reflectNum Zero)的类型只是'a'。
我很感激帮助理解这个例子,并且非常感谢与相关概念的链接。
由于
答案 0 :(得分:11)
这只是函数箭头的中缀语法让你失望。首先,这是一个易于理解的案例:Maybe Int
。为了使其与proxy s
匹配,我们只需设置:
proxy = Maybe
s = Int
现在让我们假装a -> b
写成Fun a b
,因此Zero
的类型为Fun Zero Zero
(即(Fun Zero) Zero
)。为了使其与proxy s
匹配,我们设置:
proxy = Fun Zero
s = Zero
实际上,proxy
为(->) Zero
,因此proxy s
为((->) Zero) Zero
≡(->) Zero Zero
≡Zero -> Zero
。