简体   繁体   English

具有类型类约束的类型同义词可以吗?

[英]Are type synonyms with typeclass constraints possible?

Feel free to change the title, I'm just not experienced enough to know what's really going on. 随意更改标题,我只是经验不足,无法了解实际情况。

So, I was writing a program loosely based on this , and wrote this (as it is in the original) 因此,我在基础上松散地编写了一个程序,并编写了它(如原始版本一样)

type Row a    = [a]
type Matrix a = [Row a]

Nothing special there. 没什么特别的。 However, I found myself writing a couple of functions with a type like this: 但是,我发现自己编写了一些类型如下的函数:

Eq a => Row a -> ...

So I thought that perhaps I could write this constraint into the type synonym definition, because to my mind it shouldn't be that much more complicated, right? 因此,我认为也许可以将此约束写入类型同义词定义中,因为在我看来,它应该没有那么复杂,对吗? If the compiler can work with this in functions, it should work as a type synonym. 如果编译器可以在函数中使用此功能,则它应作为类型同义词使用。 There are no partial applications here or anything or some kind of trickery (to my eyes). (在我看来)这里没有局部应用,也没有任何东西或某种欺骗手段。

So I tried this: 所以我尝试了这个:

type Row a = Eq a => [a]

This doesn't work, and the compiler suggested switching on RankNTypes . 这是行不通的,编译器建议打开RankNTypes The option made it compile, but the functions still required that I leave the Eq a => in their type declarations. 该选项使它可以编译,但是函数仍然需要我将Eq a =>保留在它们的类型声明中。 As an aside, if I tried also having a type synonym like type Matrix a = [Row a] like before, it results in an error. 顺便说一句,如果我尝试也像以前一样使用类似type Matrix a = [Row a]的类型同义词,则会导致错误。

So my question(s) are thus: 因此,我的问题是:

  • Is it possible to have a type synonym with a typeclass constraint in its definition? 是否可以在其定义中使用带有类型类约束的类型同义词?

    • If not, why? 如果没有,为什么?
  • Is the goal behind this question achievable in some other way? 这个问题背后的目标是否可以通过其他方式实现?

Constraints on a type variable can not be part of any Haskell type signature. 类型变量的约束不能成为任何Haskell类型签名的一部分。

This may seem a bit of a ridiculous statement: "what's (==) :: Eq a => a -> a -> a then?" 这似乎有点荒谬的说法:“什么是(==) :: Eq a => a -> a -> a那么?”

The answer is that a doesn't really exist, in much the same way there is not really an x in the definition fx = x * log x . 答案是a实际上并不存在,在几乎相同的方式没有真正的x定义中的fx = x * log x You've sure enough used the x symbol in defining that function, but really it was just a local tool used in the lambda-abstraction. 您已经确定在定义该函数时使用了x符号,但实际上它只是lambda抽象中使用的本地工具。 There is absolutely no way to access this symbol from the outside, indeed it's not required that the compiler even generates anything corresponding to x in the machine code – it might just get optimised away. 绝对没有办法从外部访问此符号,实际上,甚至不需要编译器甚至在机器代码中生成 x 对应的任何东西–它可能只是被优化了。

Indeed, any polymorphic signature can basically be read as a lambda expression accepting a type variable; 实际上,任何多态签名基本上都可以理解为接受类型变量的lambda表达式。 various writing styles: 各种写作风格:

(==) :: forall a . Eq a => a -> a -> a
(==) :: ∀ a . Eq a => a -> a -> a
(==) :: Λa. {Eq a} -> a -> a -> a

This is called System F . 这称为系统F。

Note that there is not really a "constraint" in this signature, but an extra argument : the Eq -class dictionary. 请注意,此签名中实际上没有“约束”,而是一个额外的参数Eq -class字典。

Usually you want to avoid having constraints in your type synonyms unless it's really necessary. 通常,除非确实需要,否则您要避免在类型同义词中使用约束。 Take the Data.Set API from containers for example. containersData.Set API为例。

Many operations in Data.Set require the elements of the set to be instances of Ord because Set is implemented internally as a binary tree. Data.Set许多操作Data.Set要求set的元素是Ord实例,因为Set在内部以二进制树的形式实现。 member or insert both require Ord memberinsert都需要Ord

member :: Ord a => a -> Set a -> Bool
insert :: Ord a => a -> Set a -> Set a

However the definition of Set doesn't mention Ord at all. 但是Set的定义根本没有提到Ord

This is because some operations on Set dont require an Ord instance, like size or null . 这是因为一些操作Set 不要需要Ord例如,像sizenull

size :: Set a -> Int
null :: Set a -> Bool

If the type class constraint was part of the definition of Set , these functions would have to include the constraint, even though it's not necessary. 如果类型类约束是Set定义的一部分,则这些函数将必须包含约束,即使不是必需的。

So yes, it is possible to have constraints in type synonyms using RankNTypes , but it's generally ill-advised. 所以是的,使用RankNTypes在类型同义词中可能有约束,但这通常是不明智的。 It's better to write the constraint for the functions that need them instead. 最好为需要它们的函数编写约束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM