我正在尝试实现一个简单的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 `<'发布于 2012-04-11 22:30:51
您需要一个类型约束才能使<正常工作:
min :: Ord a => a -> a -> Bool
-- ^^^^^发布于 2012-04-11 22:42:00
如果使用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正如莎拉所说,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
发布于 2012-04-11 23:54:43
这个问题已经有了两个答案,但我认为缺少一个重要的点:
在您的类型签名中需要(Ord a) =>的原因是,您需要将允许的类型约束到您的函数中。
当我定义一个函数function :: a -> a时,我的意思是我的函数将接受类型的数据,并返回相同类型的值。
一个很好的例子是head :: [a] -> a --给定一个any类型的列表,head将返回该列表的第一个参数。这是因为head并不真正“接触”数据本身,所以它是什么都无关紧要。
然而,您的情况并非如此:假设我们有一个数据类型Countries:
data Countries = USA | Nigeria | China | Canada -- yes, I know there are a few missing说min USA Canada或USA < Canada是没有意义的。
因此,您必须将您的函数限制为可以这样比较的类型:具有Ord (表示有序)类型类的实例的类型。限制它们的方法是在类型签名之前编写(Ord a) =>。
https://stackoverflow.com/questions/10107990
复制相似问题