简体   繁体   English

Haskell:多态函数说明

[英]Haskell: Polymorphic functions explanation

So i am given this 所以我得到了这个

intCMP :: Int -> Int -> Ordering
intCMP a b | a == b = EQ
     | a < b = LT
     | otherwise = GT

intCMPRev :: Int -> Int -> Ordering
intCMPRev a b | a == b = EQ
     | a < b = GT
        | otherwise = LT

floatCMP :: Float -> Float -> Ordering
floatCMP a b | a == b = EQ
       | a < b = LT
       | otherwise = GT

I need to write this function 我需要写这个功能

sort3 :: Ord a => (a -> a-> Ordering) -> [a] -> [a]
sort3 cmp xs =

Which will sort 3 or less elements by comparison. 通过比较将排序3个或更少的元素。 No recursion. 没有递归。 I was wondering how this works as far as passing say intCMP. 我想知道如何通过intCMP进行操作。 Why would you pass that into the sort function? 为什么将它传递给sort函数? Does it serve a purpose when sorting and returning the sorted list? 它在排序和返回排序列表时是否有目的? I'm not really sure how to do the comparisons manually like that without any sort of recursive call, so I'm just trying to understand it better. 我不确定如何手动进行比较,而无需进行任何递归调用,因此我只是想更好地理解它。

I was thinking of doing 3 comparisons and then moving the element to a certain position in the list, but i really don't know how i could even do this in haskell. 我当时想进行3个比较,然后将元素移动到列表中的某个位置,但是我真的不知道如何在haskell中执行此操作。 Any clues on how to start this would be great. 关于如何启动此功能的任何线索都很好。 Maybe some sort of pattern? 也许某种模式?

Thanks. 谢谢。

Partial answer to the first part of your question: 对问题的第一部分的部分答案:

Passing in intCMP to sort3 lets you control the way the sorting is done. 在传递intCMPsort3允许您控制排序是做的方式。 Presumably, sort3 intCMP [7,3,6] will return [3,6,7] , whereas sort3 intCMPRev [7,3,6] will return [7,6,3] . 大概, sort3 intCMP [7,3,6]将返回[3,6,7] ,而sort3 intCMPRev [7,3,6]将返回[7,6,3] You could even make your own weird sorting functions like first all the even numbers and then all the odd ones in descending order, like so: 您甚至可以创建自己的怪异排序函数,例如首先按所有偶数,然后按降序对所有奇数进行排序,如下所示:

intCMPWeird :: Int -> Int -> Ordering
intCMPWeird a b
    | even a && even b = intCMP a b -- even numbers compare as usual
    | odd a  && odd b  = intCMPRev a b  -- odd numbers compare in reverse order
    | even a && odd b  = LT -- evens are all 'smaller' than odds
    | odd a  && even b = GT -- odds are all 'greater' than evens

Using this, sort3 intCMPWeird [7,3,6] should give [6,7,3] . 使用此方法, sort3 intCMPWeird [7,3,6]应该给出[6,7,3]

What happens during typechecking when you pass one of the intCMP... functions into sort3 is (in a very small nutshell) that the compiler tries to match the type of sort3 's first argument (a -> a -> Ordering) with the type of the supplied value (Int -> Int -> Ordering) and succeeds in doing that, by making a equal to Int . 在将intCMP...函数之一传递给intCMP...时,在类型intCMP...期间发生的sort3是(简而言之)编译器尝试将sort3的第一个参数(a -> a -> Ordering) sort3 (a -> a -> Ordering) sort3 (a -> a -> Ordering)与所提供的值的类型(Int -> Int -> Ordering)和成功地这样做,通过使a等于Int Then it needs to check whether the constraint Ord a is satisfied for Int , which works! 然后,它需要检查是否约束Ord a是满足的Int ,它的工作原理! Finally the compiler can figure out that the type of sort3 intCMP is [Int] -> [Int] . 最终,编译器可以确定sort3 intCMP的类型为[Int] -> [Int] Similarly, sort3 floatCMP has type [Float] -> [Float] . 同样, sort3 floatCMP类型为[Float] -> [Float]

I'm not 100% sure why the Ord constraint is on the type of sort3 , since you can get the needed information from the passed-in comparison function - are you sure you've typed that correctly? 我不确定100%为什么Ord约束位于sort3的类型上,因为您可以从传入的比较函数中获取所需的信息-您确定输入正确吗?

EDIT: Hint on how to use a where clause to get a readable definition, you still have to fill in some bits and add some more clauses: 编辑:关于如何使用where子句获得可读定义的提示,您仍然必须填写一些位并添加更多子句:

sort3 cmp [x,y,z] 
    | x <= y && somethingElse1 = listWithXyzInSomeOrder1
    | x <= z && somethingElse2 = listWithXyzInSomeOrder2
        where a <= b = cmp a b /= GT

Here's a hint: 这里有一个提示:

  • If you have an empty list, clearly the result of sorting it will be an empty list. 如果您有一个空列表,则排序结果显然将是一个空列表。
  • Likewise, a list with just a single element is also already sorted. 同样,仅包含一个元素的列表也已排序。
  • If you have a 2-element list, there are only 2 possible orderings, hence only 2 possible return values from your function. 如果您有2个元素的列表,则只有2种可能的排序,因此函数中只有2种可能的返回值。
  • If you have a 3-element list, there are 6 possible orderings (the first element can be 1 of 3 input elements, the next element can be 1 of the 2 remaining, leaving only 1 choice for the last element). 如果您有一个由3个元素组成的列表,则有6种可能的排序(第一个元素可以是3个输入元素中的1个,下一个元素可以是剩余2个元素中的1个,最后一个元素只有一个选择)。 You can easily write down the 6 different conditions, causing you to return 1 of the 6 possible lists of the 3 elements. 您可以轻松地写下6个不同的条件,从而使您返回3个元素的6个可能列表中的1个。

You're not writing polymorphic functions (which is by definition a function that takes more than one type). 您不是在编写多态函数(根据定义,该函数需要多个类型)。 Write one first: 首先写一个:

cmp :: Ord a => a -> a -> Ordering
cmp x y =
  | x == y = EQ
  | x < y  = LT
  | otherwise = GT

You would write the above that way the functionality that compares the elements in the sort, need not be a part of the sort. 您将以这种方式编写上面的代码,该功能可以比较排序中的元素,而不必成为排序的一部分。 To sort a list is by nature recursive: at least if length is undefined. 对列表进行排序本质上是递归的:至少在未定义长度的情况下。 To achieve this simply write a sort that can make use of your custom comparison, here is quick sort though you could write a different type of sort. 为此,只需编写一个可以利用自定义比较的排序,尽管您可以编写其他类型的排序,但这是一种快速排序。

sort3 :: (Ord a) => [a] -> [a]  
sort3 [] = []  
sort3 (x:xs) =   
    let smallerSorted = filter (<=)
        biggerSorted = filter(>)
    in  smallerSorted ++ [x] ++ biggerSorted  

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

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