是否可以使用类型类约束的类型同义词?

随意更改标题,我只是没有足够的经验知道真正发生了什么。

所以,我在这个基础上松散地编写了一个程序,并且写了这个程序(因为它是原始的)

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

没有什么特别的。 但是,我发现自己用这样的一个类型编写了几个函数:

Eq a => Row a -> ...

所以我想,也许我可以将这个约束写入类型同义词定义中,因为在我看来,它不应该那么复杂,对吗? 如果编译器可以在函数中使用它,它应该作为一个类型的同义词工作。 这里没有部分应用程序或任何东西或某种欺骗(对我来说)。

所以我试过这个:

type Row a = Eq a => [a]

这不起作用,编译器建议切换RankNTypes 。 该选项使它能够编译,但函数仍然要求我将Eq a =>留在它们的类型声明中。 顺便说一句,如果我尝试type Matrix a = [Row a]像以前一样type Matrix a = [Row a]的类型同义词,则会导致错误。

所以我的问题是这样的:

  • 在它的定义中是否有可能具有类型类型约束的类型同义词?

  • 如果不是,为什么?
  • 这个问题背后的目标是否可以通过其他方式实现?


  • 类型变量上的约束不能成为任何Haskell类型签名的一部分。

    这似乎有点荒谬的说法:“什么是(==) :: Eq a => a -> a -> a然后?”

    答案是a实际上并不存在,在几乎相同的方式没有真正的x定义中的fx = x * log x 。 你已经确定在定义该函数时使用了x符号,但实际上它只是在lambda抽象中使用的本地工具。 从外部访问这个符号绝对没有办法,事实上,编译器甚至不需要在机器代码中生成与x相对应的任何东西 - 它可能只是被优化掉了。

    事实上,任何多态签名基本上都可以读为接受类型变量的lambda表达式; 各种写作风格:

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

    这被称为系统F.

    请注意,是不是真的在此签名“约束”,而是一个额外的参数:该Eq -class字典。


    通常你想避免在你的类型同义词中有约束,除非它真的有必要。 例如,从containers取得Data.Set API。

    Data.Set许多操作要求该集合的元素是Ord实例,因为Set在内部实现为二叉树。 memberinsert都需要Ord

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

    然而, Set的定义完全没有提及Ord

    这是因为Set上的一些操作不需要Ord实例,如sizenull

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

    如果类型约束是Set定义的一部分,这些函数将不得不包含约束,即使它不是必需的。

    所以是的,可能在使用RankNTypes类型同义词中存在约束,但通常是不明智的。 最好为需要它们的函数编写约束。

    链接地址: http://www.djcxy.com/p/43531.html

    上一篇: Are type synonyms with typeclass constraints possible?

    下一篇: Using the Maybe Monad in "reverse"