Haskell:为什么这种类型检查?

时间:2012-01-23 22:56:55

标签: reflection haskell typechecking

这是一个取自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'。

我很感激帮助理解这个例子,并且非常感谢与相关概念的链接。

由于

1 个答案:

答案 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 ZeroZero -> Zero