此特定代码部分的目的是使size
函数比简单计算elems
中的所有元素更有效。我已经决定对构成列表的两种类型求和,但我似乎无法创建大小函数的签名。
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)
从Prelude,我们知道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
当然在上下文中有意义,但我真的不知道如何匹配Either a b
。
有人有任何想法吗?
答案 0 :(得分:25)
Either a b
类型的内容可以是Left 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)
答案 1 :(得分:0)
问题似乎是你需要size
的伪参数,但是你不能在a
b
中为Either a b
和elems
两种类型传递假人。也许您可以使用size _ = (size . head) (elems :: [a]) + (size . head) (elems :: [b])
来获取每种类型的假人:
{{1}}
答案 2 :(得分:0)
我认为你遇到的核心问题是你想要一个同时表示来自其他两种类型的数据的类型。 Either a b
在给定时间只能是a
或b
中的一个。
同时表示a
和b
的简单数据类型是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)
代表什么?成员函数定义是什么?