在SPJ 的这篇论文的第 3 页和第 4 页中,写道:
class Mutation m where
type Ref m :: * -> *
newRef :: a -> m (Ref m a)
readRef :: Ref m a -> m a
writeRef :: Ref m a -> a -> m ()
instance Mutation IO where
type Ref IO = IORef
newRef = newIORef
readRef = readIORef
writeRef = writeIORef
instance Mutation (ST s) where
type Ref (ST s) = STRef s
newRef = newSTRef
readRef = readSTRef
writeRef = writeSTRef
和:
类声明现在引入了类型函数 Ref(具有指定的种类)以及通常的值函数,例如 newRef(每个都具有指定的类型)。类似地,每个实例声明都提供了一个子句,该子句定义实例类型的类型函数以及每个值函数的见证。
我们说 Ref 是一个类型族,或类 Mutation 的关联类型。它的行为类似于 类型级别的函数,因此我们也将 Ref 称为类型函数。应用类型函数使用与应用类型构造函数相同的语法:上面的 Ref ma 表示将类型函数 Ref 应用于 m,然后将生成的类型构造函数应用于 a。
所以,换句话说,
Ref :: (*->*)->*->*
也就是说,Ref
将类型级别函数作为参数,如Maybe
or IO
or[]
并生成另一个类型级别函数,例如IORef
使用模式匹配,即Ref
由模式匹配定义。
那么,怎么可能在类型级别而不是值级别上对函数进行模式匹配呢?
例如,
fun2int:: (Int->Int)->Int
fun2int (+)=2
fun2int (*)=3
不可能写,因为函数的相等性是不可判定的。
1)那么在类型级别上这怎么可能没有问题呢?
2)是因为类型级别的功能非常有限吗?因此,类型级别上的任何类型的函数都不能作为参数Ref
,只有少数选择,即程序员声明的函数,而不是像 (+) 这样的函数,它们比程序员声明的函数更通用?这就是类型级别函数模式匹配没有问题的原因吗?
3) 这个问题的答案是否与GHC 规范的这一部分有关?