当具有参数化类型时:data A a=X a| Y
我已尝试(成功)实现 Functor
和 Applicative
不指定类型参数:instance Functor A where
而不是 instance Functor (A a) where
.为什么它有效?查看 LYAH似乎所有示例都在其所有 typeclass instances
中指定了类型参数.
什么时候应该忽略类型参数?
最佳答案
instance Functor A where
instead ofinstance Functor (A a) where
. Why does it work ?
我发现使用 GHC 的分类系统更容易理解这一点。让我们从一个简单的案例开始,在 GHCi 中进行实验:
> :k Eq Int
Eq Int :: Constraint
这告诉我们
Eq Int
是一个约束,一些可以在类型检查期间验证的属性。事实上,如果我们输入 check (12 :: Int) == (42 :: Int)
,编译器将验证整数可以比较,解决约束 Eq Int
.什么是
Eq
单独,没有 Int
的类的名称范围?> :k Eq
Eq :: * -> Constraint
这告诉我们
Eq
可以认为是从类型(*
是一种类型)到约束的函数。确实,在
Eq Int
, Int
是一个类型,所以我们有 Int :: *
制作Int
传递给 Eq
的善意论据.类型类已经够多了,那么类型构造函数呢?
> :k Maybe Int
Maybe Int :: *
毫不奇怪,
Maybe Int
是一种类型> :k Maybe
Maybe :: * -> *
Maybe
相反,它是一个从类型到类型的函数( *->*
)。这确实是Maybe
类型构造函数:将类型 ( Int
) 映射到类型 ( Maybe Int
)。回到最初的问题。为什么我们不能写
instance Functor (A a)
但我们可以改为 instance Functor A
?嗯,我们有> :k A Int
A Int :: *
> :k A
A :: * -> *
而且,最重要的是,
> :k Functor
Functor :: (* -> *) -> Constraint
这告诉我们
Functor
的类型类型类与 Eq
不同类型类。 Eq
需要一个类型作为参数,而 Functor
期待某种东西(* -> *)
作为论据。 A
适合那种,而 A Int
才不是。当在类的定义中将参数应用于其他类型时,就会发生这种情况。例如。
class C1 a where
foo :: a -> Bool
结果
C1 :: * -> Constraint
.反而,class C2 f where
bar :: f Int -> Bool
结果
C2 :: (* -> *) -> Constraint
, 自 f
本身不用作类型,f Int
是,所以 f
必须是类型的参数化类型 * -> *
.
关于haskell - 为什么参数化类型实例在不指定类型参数的情况下工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56143399/