哈斯克尔和奥德

时间:2012-04-11 14:28:47

标签: haskell

我正在尝试实现一个简单的min函数,它接受两个参数&如果第一个必须按排序顺序出现在第二个之前,则返回True,否则返回False:

min :: a -> a -> Bool
min a b = if a < b then True else False

我明白了:

No instance for (Ord a)
arising from a use of `<'

3 个答案:

答案 0 :(得分:25)

如果您look at the documentation,您会看到(<)的类型为

(<) :: a -> a -> Bool

这是误导!

类型声明出现在类型类定义中:

class Eq a => Ord a where ...

所以完整类型是

(<) :: Ord a => a -> a -> Bool

顺便说一句,如果你问ghci (<)的类型是什么,它会正确的。

Prelude> :t (<)
(<) :: (Ord a) => a -> a -> Bool

另请注意,在同一类型类中已经有一个名为min的函数。

min :: Ord a => a -> a -> a

因此,除非您隐藏原始min,否则无法调用您的函数min。 (我不打算告诉你如何。改为使用不同的名称。)


最后,你现在有了

min :: Ord a => a -> a -> Bool
min a b = if a < b then True else False

正如Sarah所说,if blah then True else Falseblah相同,因此您可以简化为更清晰的

min :: Ord a => a -> a -> Bool
min a b = a < b

现在,Haskell中的运算符只是具有有趣名称的函数 - 这与

相同
min :: Ord a => a -> a -> Bool
min a b = (<) a b

我们可以进一步简化:

min :: Ord a => a -> a -> Bool
min = (<)

因此min只是(<)的另一个名称。为什么不简单地使用原始<而不是min

答案 1 :(得分:8)

已经有两个答案,但我认为有一个重要的缺失:

您的类型签名中需要(Ord a) =>原因是您需要约束允许“进入”您的函数的类型。

当我定义一个函数function :: a -> a时,我说我的函数将采用任何类型的数据,并返回相同类型的值。

一个很好的例子是head :: [a] -> a - 给定一个任何类型的列表,head将返回列表的第一个参数。这是因为head并没有真正“触摸”数据本身,所以它根本不重要。

但是,你的情况不是这样的:假设我们有一个数据类型国家:

data Countries = USA | Nigeria | China | Canada -- yes, I know there are a few missing

min USA CanadaUSA < Canada是没有意义的。

因此,您必须将函数限制为可以这种方式进行比较的类型:具有Ord(含义的)类型类实例的类型。限制它们的方法是在类型签名之前写(Ord a) =>

答案 2 :(得分:7)

您需要<的类型约束才能工作:

min :: Ord a => a -> a -> Bool
--     ^^^^^