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

cro*_*eea 6 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
Run Code Online (Sandbox Code Playgroud)

在GHCi中,我得到以下内容:

>:t Zero
Zero :: Zero -> Zero
Run Code Online (Sandbox Code Playgroud)

这是有道理的:我要求构造函数的类型取零并返回零.

>:t reflectNum
reflectNum :: (ReifiesNum s, Num a) => proxy s -> a
Run Code Online (Sandbox Code Playgroud)

我有可能写出类似的东西

>let x = Just (undefined::Zero)
>reflectNum x
Run Code Online (Sandbox Code Playgroud)

因为类型Just Zero匹配类型变量'proxy s'.

最后,令人困惑的部分:

>:t (reflectNum Zero)
(reflectNum Zero) :: Num a => a
Run Code Online (Sandbox Code Playgroud)

我不明白构造函数Zero :: Zero - > Zero的类型如何显然匹配类型变量'proxy s',但显然它确实是因为(reflectNum Zero)的类型只是'a'.

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

谢谢

ehi*_*ird 11

它只是函数箭头的中缀语法,让你失望.首先,这是一个易于理解的案例:Maybe Int.为了使其匹配proxy s,我们只需设置:

proxy = Maybe
s = Int
Run Code Online (Sandbox Code Playgroud)

现在让我们假装a -> b是写的Fun a b,所以Zero有类型Fun Zero Zero(即(Fun Zero) Zero).为了使其匹配proxy s,我们设置:

proxy = Fun Zero
s = Zero
Run Code Online (Sandbox Code Playgroud)

在现实中,proxy(->) Zeroproxy s((->) Zero) Zero(->) Zero ZeroZero -> Zero.

  • @Eric`( - >)Zero`不是有效类型,它是*类型构造函数*,需要应用于另一种类型以形成具体类型."可能"也是如此; 没有类型`Maybe`的值,但是有类型`Maybe Int`,`Maybe [Double]`,`Maybe(Maybe(Maybe Char))`等的值.同样,没有类型的值` ( - >)Zero`,但是有类型`( - >)Zero Zero`的值,即`Zero - > Zero`. (3认同)