代码之家  ›  专栏  ›  技术社区  ›  Fry

你如何与“A B”型匹配?

  •  12
  • Fry  · 技术社区  · 14 年前

    代码的这一特定部分的目的是 size 比简单地计算 elems . 我已经决定对组成列表的两种类型求和,但似乎无法创建size函数的签名。

    instance (Finite a, Finite b) => Finite (Either a b) where
        elems = combineLists [Left x | x <- elems] [Right x | x <-elems]
        size ??? = (size a) + (size b)
    

    从序曲,我们知道 Either a b = Left a | Right b .

    我尝试的第一件事就是 Either 但它当然是一种类型,所以不起作用。接下来,我试着 ((Left a) | (Right b)) 但也不要继续。似乎没有其他匹配的类型 Either a b .

    我能得到 size (Left a) 编译,但由于它缺少 b 组件,我收到错误:

    Ambiguous type variable `b' in the constraint:
      `Finite b' arising from a use of `size' at <interactive>:1:0-12
    

    这在上下文中当然有意义,但我真的不知道如何匹配 要么是B .

    有人有什么想法吗?

    3 回复  |  直到 7 年前
        1
  •  25
  •   sth Alien    14 年前

    某种类型的东西 Either a b 要么是 Left a 或A Right b ,因此有两种情况可以分别处理:

    size (Left x) = size x
    size (Right x) = size x
    

    关于不明确类型变量的错误是一个单独的问题。 如果你只是输入 size (Left 1) 在解释器中,系统无法推断出“正确”的类型 Left 1 价值是。它可能是 Either Int anything 只要不知道那是什么类型 anything 是的,如果在课堂上就不能检查 Finite (这是 size )

    可以通过指定显式类型签名来避免该问题:

    size (Left 1 :: Either Int String)
    
        2
  •  0
  •   Nefrubyr    14 年前

    问题似乎是你需要一个虚假的理由 size 但是你不能通过两种类型的假人 a b 在单一 Either a b . 也许你可以用 elems 要获得每种类型的虚拟对象:

    size _ = (size . head) (elems :: [a]) + (size . head) (elems :: [b])
    
        3
  •  0
  •   MtnViewMark    14 年前

    我认为您所面临的核心问题是,您需要一个同时表示两个其他类型的数据的类型。 Either a b 只能是 a b 在给予的时间。

    一个简单的数据类型,它表示 和A 同时是2元组。这种东西的类型签名是 (a, b) ,也是创建一个的表达式,因此模式加工一个:

    > :type (4,5)
    (4,5) :: (Num t, Num t1) => (t, t1)
    > let f (a, b) = 2*a + b
    > f (4,5)
    13
    

    您应该考虑使用2元组编写第一行,如下所示:

     instance (Finite a, Finite b) => Finite (a, b) where
    

    这是什么 Finite (a, b) 代表什么?成员函数定义是什么?