这是从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 ZeroZero -> Zero

10-06 13:29
查看更多