我正在尝试实现一个简单的 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 `<'
我正在尝试实现一个简单的 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 `<'
如果您查看文档,您将看到 for 的类型(<)
为
(<) :: 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
正如莎拉所指出的,if blah then True else False
与 相同blah
,因此您可以简化为更清晰
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
?
已经有两个答案,但我认为缺少一个重要的点:
您需要在类型签名中的原因是您需要限制允许“进入”您的函数的类型。(Ord a) =>
当我定义一个函数function :: a -> a
时,我是说我的函数将获取任何类型的数据,并返回一个相同类型的值。
A good example of this is head :: [a] -> a
-- given a list of any type, head will return the list's first argument. This is because head doesn't really "touch" the data itself, so it doesn't matter at all what it is.
However, your situation isn't like that: imagine we have a data type Countries:
data Countries = USA | Nigeria | China | Canada -- yes, I know there are a few missing
It makes no sense to say min USA Canada
or USA < Canada
.
Therefore you have to restrict your functions to types which can be compared this way: types which have instances of the Ord
(meaning ordered) typeclass. The way you restrict them is by writing (Ord a) =>
before your type signature.
您需要一个类型约束<
才能工作:
min :: Ord a => a -> a -> Bool
-- ^^^^^