Haskell混淆类型类/多态

时间:2014-08-09 16:14:22

标签: haskell types polymorphism

所以基本上我已经过去一个月前学习这部分了,我可以做更复杂的事情,但我还是不明白我什么时候需要" Ord"或者" Eq"我的类型定义中的等等。当我在网上查看它时,由于某种原因,它让我感到困惑。

E.g。

my_min :: Ord a => a -> a -> a
my_min n1 n2 = if n1<n2 then n1 else n2

为什么这需要Ord?你能举例说明你何时需要Eq(非常简单)?我需要一个非常明确的基本解释,说明何时需要提出这些内容,需要注意什么,以及如何尽可能避免使用这些内容。

通常我只需要&#34; [Int] - &gt; Int - &gt; [INT]&#34;所以我知道这个函数需要一个整数列表和一个整数,并返回一个整数列表。但当它包括Eq或Ord时我不知道。

这个Eq类型在这个例子中我发现在我的讲义中发现两个列表是相同的,它是如何应用的?

identical :: Eq a =>[a]->[a]->Bool 
identical [] [] = True 
identical [] _ = False 
identical _ [] = False 
identical (h1:t1) (h2:t2) =
    if h1==h2 
        then (identical t1 t2) 
        else False 

谢谢。

2 个答案:

答案 0 :(得分:5)

Ord表示该事物可以被订购,这意味着可以ab更小(或更大)。仅使用Eq就像是说:我知道这两个项目不一样,但我不能说哪一个更大或更小。例如,如果您将红绿灯作为数据类型:

data TLight = Red | Yellow | Green deriving (Show, Eq)

instance Eq TLight where
  Green == Green = True
  Yellow == Yellow = True
  Red == Red = True
  _ == _ = False

现在我们可以说:Red不等于Yellow,但我们不能说更重要的是什么。这就是您无法在TLight中使用my_min的原因。你不能说哪一个更大。

关于第二个问题:&#34;是否有必须使用EqOrd的情况?&#34;:

Ord 暗示 Eq。这意味着如果可以订购类型,您也可以检查它是否相等。

你说你主要处理[Int] -> Int -> [Int]然后你知道它需要一个整数列表和一个整数并返回一个整数。现在,如果你想要概括你的功能,你必须问自己:我想在我的功能中使用的可能类型是否需要任何特殊功能?就像它们必须能够被订购或等同一样。

让我们举几个例子:假设我们要编写一个函数,它接受类型a的列表和类型a的元素,并返回带有元素的lisy。它的签名样式怎么样?让我们开始吧:

consfunc :: [a] -> a -> [a]

我们还需要更多功能吗?没有!我们的类型a可以是任何东西,因为我们不需要它可以被简单地排序,因为这是我们的函数应该做的事情。

现在如果我们想要一个列表和一个元素并检查该元素是否已经在列表中呢?开始类型签名是:

elemfunc :: [a] -> a -> Bool

现在我们的元素必须能够做一些特别的事吗?是的,我们必须能够检查它是否等于列表中的任何元素,这表示我们的类型a必须是等同的,所以我们的类型签名如下所示:

elemfunc :: (Eq a) => [a] -> a -> Bool

现在如果我们想要一个列表和一个元素并且如果它小于第一个元素则插入它?你能猜出类型签名会是什么样子吗?

让我们再次从标准开始并问自己:我们需要的不仅仅是知道元素和列表必须属于同一类型:是的,因为我们的条件需要执行一个需要我们的类型的测试有序,我们必须在我们的类型签名中包含Ord

conditionalconsfunc :: (Ord a) => [a] -> a -> [a]

编辑:

你想知道两个列表是否相同,所以有两件事需要注意:

您的列表必须包含相同的类型列表中的内容必须是等同的,因此Eq

答案 1 :(得分:2)

如果您使用的是Int等固定类型,则永远不需要类约束。这些仅在使用多态代码时出现。

如果您使用Eq==函数,或者您调用其他任何函数,则需要/=。 (即,如果您调用其类型中包含Eq的函数,那么您的类型也需要Eq。)

如果您使用Ord<>或类似功能,则需要compare。 (再次,或者如果你打电话的话。)

请注意,如果您只进行模式匹配,则需要Eq。因此,以下是不同的:

factorial 1 = 1
factorial n = n * factorial (n-1)
-- Only needs Num.

factorial n = if n == 1 then 1 else  n * factorial (n-1)
-- Needs Num and Eq.

factorial n = if n < 2 then 1 else n * factorial (n-1)
-- Needs Num, Eq and Ord. (But Ord implies Eq automatically.)