这是从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 Just匹配类型变量'proxy s'。
最后,令人困惑的部分是:
>:t (reflectNum Zero)
(reflectNum Zero) :: Num a => a
我不明白构造函数的类型零::零->零显然与类型变量'proxy s'匹配,但是显然可以,因为(reflectNum Zero)的类型只是'a'。
我将不胜感激帮助您理解此示例,并且非常感谢与相关概念的链接。
谢谢
最佳答案
这只是功能箭头的中缀语法,使您无法自拔。首先,这是一个简单易懂的示例: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
。