【问题标题】:Type-class instances for types with 2 parameters when the type-class has only one当类型类只有一个时,具有 2 个参数的类型的类型类实例
【发布时间】:2011-07-19 12:26:52
【问题描述】:

考虑以下类型类:

class Listable a where
   asList :: a t -> [t]

用一个参数为类型创建实例很容易:

instance Listable [] where
   asList = id

instance Listable Maybe where
   asList (Just x) = [x]
   asList Nothing = []

现在我将如何为具有两个相同类型参数的对创建一个实例?当然我可以做一些包装:

data V2 a = V2 a a

v2 (p,q) = V2 p q

instance Listable V2 where
   asList (V2 p q) = [p,q]

现在我可以写asList $ v2 (47, 11) 之类的东西,但这样就达不到目的了。

有没有办法将 pair 的类型限制为两个类型参数相等的情况,并为此编写一个 Listable 实例?如果不是,通常的解决方法是什么?

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    从概念上讲,有很多方法可以做到这一点。不幸的是,它们中的大多数实际上都不起作用。唉!

    首先,作为一名函数式程序员,我敢打赌这是你真正想要写的:

    instance Listable (\a -> (a, a)) where
        asList (p, q) = [p,q]
    

    不幸的是,类型级别的 lambda 表达式不存在。我们可以使用类型同义词编写上述 lambda 的命名版本:

    type Same2 f a = f a a
    
    instance Listable (Same2 (,)) where { ... }
    

    这也是不允许的,因为类型同义词没有完全应用。相反,我们可以想象类型类采用一个额外的参数来描述如何应用类型变量:

    class Listable app f where
        asList :: app f a -> [a]
    
    instance Listable __ Maybe where { ... }
    
    instance Listable __ (,) where { ... }
    

    甚至没有考虑app 可能是什么,这也失败了,因为我们没有为f 参数提供一致的类型。

    继续讨论实际可行的事情,我认为最常见的方法是将类型同义词方法包装在 newtype 中,然后只处理涉及的包装和展开。

    newtype Same2 f a = Same2 (f a a)
    
    instance Listable (Same2 (,)) where { ... }
    

    它是可行的,如果有点难看。您也可以通过这种方式定义类型构造函数组合和其他玩具,然后将类型级无点表达式埋在一堆跳环样板下发疯。

    作为最后一种方法,您还可以“反向”编码上面的 lambda 样式方法,完全应用的版本,单一类型参数:

    class Listable t where
        type ListableElem t :: *
        asList :: t -> [ListableElem t]
    

    能够做这种事情是字体家族的主要动机之一。用 MPTC 和 fundeps 可以表达同样的事情,但它 1) 等效,2) 更丑陋,所以我不会费心写出来。

    【讨论】:

    • 很抱歉懒得尝试,但最后一种方法允许instance Listable (a,a) - 不是吗?
    • @yatima2975:以(,) 作为最外层类型构造函数的不同实例为代价,是的。既然你提到了它,可能应该在我的回答中把它作为一个例子......
    【解决方案2】:

    你必须定义一些包装类型来做到这一点。 (不过,您应该使用 newtype。)您甚至可以定义:

    newtype Foo t a = Foo(t a a)
    
    instance Listable (Foo (,)) where
       asList (Foo (a,b)) = [a,b]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 2015-09-07
      • 2018-09-15
      • 2013-03-04
      相关资源
      最近更新 更多