[英]Haskell kind system vs type families and multi param type classes
在 Haskell 中,我发现很难完全掌握类系统的目的,以及它真正为语言添加了什么。
我知道有种类会增加安全性。 例如,考虑fmap :: (a -> b) -> fa -> fb
与它的单一版本fmap2 :: (a -> b) -> p -> q
。
我的理解是,多亏了这种系统,我可以事先更详细地指定数据的形状应该是什么。 更好,因为类型检查器可以检查更多,更严格的要求将降低用户混淆类型的可能性。 这将减少编程错误的可能性。 我相信这是种类的主要动机,但我可能是错的。
现在我认为 fmap2 可以具有与 fmap 相同的实现,因为它的类型是不受约束的。 这是真的吗?
是否可以将 base/ghc 库中的所有多种类类型替换为单种类类型,并且它仍然可以正确编译?
为了澄清一点,我的意思是对于像这样的类:
class Functor f where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
我可能会用类似的东西代替它
class Functor a b p q where
fmap :: (a -> b) -> p -> q
(<$) :: a -> q -> p
像这样的Functor
实例
instance Functor [] where fmap = map
我可能会替换它
instance Functor a b p q where fmap = map
备注:这不会按原样工作,因为我还需要修改map
并沿着依赖链向下走。 以后会考虑更多。。
我想弄清楚种类是否不仅仅增加了安全性? 我可以用多种类型做一些我不能用单种类做的事情吗?
备注:这里我忘了提到我通常使用一些语言扩展,通常是为了在编写类时提供更大的灵活性。 在做 vanilla haskell 时,使用的东西真的很有意义。 但是当我开始使用类型系列和一些其他扩展时,我根本不需要种类就变得不太清楚了。
我记得有一些可单次遍历的库,它使用单一类型重新实现了许多标准库函数,并使用类型族来泛化签名。 这就是为什么我的直觉是,如果使用类型家族,多种类变量可能不会真正增加那么多的表达能力。 然而,这样做的一个缺点是你失去了类型安全。 我的问题是你真的只是失去了那个,还是你真的失去了其他东西。
让我们备份。 你似乎认为因为签名
id2 :: a -> b
比
id :: a -> a
id2
可以与id
具有相同的实现。 但事实并非如此。 事实上id2
没有完整的实现(任何id2
实现都涉及无限循环或undefined
)。
普遍性的结构会产生“压力”,而这种压力是我们必须导航才能为某事找到正确类型的原因。 如果f
是不是更宽泛g
,这意味着任何地方g
可以使用, f
也,但它也意味着,任何实现f
是一个有效的实现g
。 因此,在使用站点上,它朝一个方向发展,而在定义站点上,它朝另一个方向发展。
我们可以使用id2
任何地方,我们也可以使用id
,但签名id2
是如此普遍,这是不可能实现的。 签名越通用,可以使用的上下文就越多,但实现的可能性也就越小。 我想说一个好的类型签名的主要目标是找到尽可能少的预期函数实现的通用级别,而不是完全不可能编写。
您提议的签名fmap2 :: (a -> b) -> p -> q
与id2
一样,非常通用,无法实现。 -kinded更高类型的目的是给我们的工具,有一个像很一般签名fmap
,这是不是太笼统像fmap2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.