繁体   English   中英

Haskell:多态函数说明

[英]Haskell: Polymorphic functions explanation

所以我得到了这个

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

我需要写这个功能

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

通过比较将排序3个或更少的元素。 没有递归。 我想知道如何通过intCMP进行操作。 为什么将它传递给sort函数? 它在排序和返回排序列表时是否有目的? 我不确定如何手动进行比较,而无需进行任何递归调用,因此我只是想更好地理解它。

我当时想进行3个比较,然后将元素移动到列表中的某个位置,但是我真的不知道如何在haskell中执行此操作。 关于如何启动此功能的任何线索都很好。 也许某种模式?

谢谢。

对问题的第一部分的部分答案:

在传递intCMPsort3允许您控制排序是做的方式。 大概, sort3 intCMP [7,3,6]将返回[3,6,7] ,而sort3 intCMPRev [7,3,6]将返回[7,6,3] 您甚至可以创建自己的怪异排序函数,例如首先按所有偶数,然后按降序对所有奇数进行排序,如下所示:

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

使用此方法, sort3 intCMPWeird [7,3,6]应该给出[6,7,3]

在将intCMP...函数之一传递给intCMP...时,在类型intCMP...期间发生的sort3是(简而言之)编译器尝试将sort3的第一个参数(a -> a -> Ordering) sort3 (a -> a -> Ordering) sort3 (a -> a -> Ordering)与所提供的值的类型(Int -> Int -> Ordering)和成功地这样做,通过使a等于Int 然后,它需要检查是否约束Ord a是满足的Int ,它的工作原理! 最终,编译器可以确定sort3 intCMP的类型为[Int] -> [Int] 同样, sort3 floatCMP类型为[Float] -> [Float]

我不确定100%为什么Ord约束位于sort3的类型上,因为您可以从传入的比较函数中获取所需的信息-您确定输入正确吗?

编辑:关于如何使用where子句获得可读定义的提示,您仍然必须填写一些位并添加更多子句:

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

这里有一个提示:

  • 如果您有一个空列表,则排序结果显然将是一个空列表。
  • 同样,仅包含一个元素的列表也已排序。
  • 如果您有2个元素的列表,则只有2种可能的排序,因此函数中只有2种可能的返回值。
  • 如果您有一个由3个元素组成的列表,则有6种可能的排序(第一个元素可以是3个输入元素中的1个,下一个元素可以是剩余2个元素中的1个,最后一个元素只有一个选择)。 您可以轻松地写下6个不同的条件,从而使您返回3个元素的6个可能列表中的1个。

您不是在编写多态函数(根据定义,该函数需要多个类型)。 首先写一个:

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

您将以这种方式编写上面的代码,该功能可以比较排序中的元素,而不必成为排序的一部分。 对列表进行排序本质上是递归的:至少在未定义长度的情况下。 为此,只需编写一个可以利用自定义比较的排序,尽管您可以编写其他类型的排序,但这是一种快速排序。

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