繁体   English   中英

哈斯克尔和奥德

[英]Haskell and Ord

我正在尝试实现一个接受两个参数的简单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 `<'

如果查看文档 ,您将看到(<)的类型为

(<) :: 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

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

你需要的原因 (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) =>

你需要< to work的类型约束:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM