如何正确应用文件夹功能

时间:2019-02-05 14:34:31

标签: haskell syntax fold

我试图找到列表的max元素,其中的元素是我自己创建的数据类型,使用fold而不是递归地进行操作。但是,我最终遇到错误“无法匹配类型”。作为Haskell的新手,我看不到问题并希望知道如何正确应用foldr函数。

我尝试获取最大元素的方法如下:

-(文件夹比较(头列表)(尾列表))

无法编译。

我包括了Eq和Ord的数据类型及其实例,还包括了比较功能。

 -- Car data type

 data Car = Car {registration :: String,
                    hour :: Integer, 
                  minute :: Integer, 
               tupleForm :: PTime
           }

-- Equality comparison between Car data types
-- reqiures equality by registration number, hours and minutes

instance Eq Car where 
     (Car r1 h1 m1 _) == (Car r2 h2 m2 _) = (r1 == r2) && (((h1*60)+m1) == 
((h2*60)+m2))

-- Order comparison between Car data types
-- Compares time of two Cars , hours and minutes 

instance Ord Car where 
     compare (Car _ h1 m1 _) (Car _ h2 m2 _) = compare ((h1*60)+m1) 
     ((h2*60)+m2)  


-- Returns the larger Car
comparison :: (Car,Car) -> Car
comparison(car1,car2) = if(car1 > car2) then car1 else car2

折叠汽车列表后,我的预期结果是获得“最大汽车”,这基本上意味着时间最长的汽车。但是由于类型错误,我最终遇到了编译错误。

2 个答案:

答案 0 :(得分:3)

问题是comparison的类型和定义。

首先,类型应为Car -> Car -> Car:您需要两个 Car值并返回较大的值。

第二,您对comparison的定义尝试将单个参数匹配为元组,而不是两个单独的参数。删除括号和逗号。

comparison :: Car -> Car -> Car
comparison car1 car2 = if car1 > car2 then car1 else car2

(当然,comparison仅限于max而非Car的{​​{1}}。

Ord a => a

而且,正如罗宾·齐格蒙德(Robin Zigmond)所指出的,comparison :: Car -> Car -> Car comparison = max 基本上是foldr comparison x,具有适当的值maximum。)

答案 1 :(得分:1)

考虑简化的foldr类型。

foldr :: (a -> b -> b) -> b -> [a] -> b

这比您需要的要通用得多,因为您要处理所有汽车。这意味着要用Car找到最大的foldr,类型变为

foldr :: (Car -> Car -> Car) -> Car -> [Car] -> Car

第一个参数是在两个Car之间选择的函数。在您的情况下,您想要max,因为它的类型

max :: Ord a => a -> a -> a

成为

max :: Car -> Car -> Car

并完全匹配。

foldr的第二个参数被命名为z,代表零。它是折叠过程的种子。为此,您也可以使用通过head获得的列表的第一个元素。

类型[Car]的列表参数显然是您要计算其最大值的列表。您可以传递整个列表,但是头部已经作为z自变量。最好是tail list

给出以下列表(在修改Car以删除tupleForm并派生Show实例之后)

cars = [ Car "A" 1 2, Car "B" 3 4, Car "C" 10 10 ]

foldr找到最大值是

λ> foldr max (head cars) (tail cars)
Car {registration = "C", hour = 10, minute = 10}

请注意,此foldr的应用等效于maximum,但您不必完全相信。添加

import Test.QuickCheck

在源文件顶部,然后

prop_max :: [Car] -> Property
prop_max l =
  not (null l) ==>
    maximum l == foldr max (head l) (tail l)

instance Arbitrary Car where
  arbitrary = do
    r <- oneof $ map return ["Apple","Orange","Banana"]
    h <- choose (0,23)
    m <- choose (0,59)
    return (Car r h m)

使该断言更具信心。

λ> quickCheck prop_max
+++ OK, passed 100 tests.