如何正确应用foldr功能
how to correctly apply the foldr function
我试图找到列表的最大元素,其中元素是我自己创建的数据类型,使用折叠而不是递归地进行。但是我最终遇到错误 "couldn't match type"。由于我是 haskell 的新手,我无法理解问题并希望知道如何正确应用 foldr 函数。
我尝试获取最大的元素是这样的:
-- (foldr comparison (head list) (tail list))
无法编译。
我已经包括了 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
折叠 Car 列表后我的预期结果是获得 'largest car' ,这基本上意味着时间最长的汽车。但是由于类型错误,我最终遇到了编译错误。
问题是 comparison
的类型和定义。
首先,类型应该是 Car -> Car -> Car
:你取 两个 Car
个值和 return 个较大的值。
其次,您对 comparison
的定义尝试将 单个 参数匹配为一个元组,而不是两个单独的参数。删除括号和逗号。
comparison :: Car -> Car -> Car
comparison car1 car2 = if car1 > car2 then car1 else car2
(当然,comparison
只是max
限制在Car
而不是Ord a => a
。
comparison :: Car -> Car -> Car
comparison = max
而且,正如 Robin Zigmond 指出的那样,foldr comparison x
基本上是 maximum
的适当值 x
。)
考虑foldr
的简化类型。
foldr :: (a -> b -> b) -> b -> [a] -> b
这比您需要的要通用得多,因为您要处理所有汽车。也就是说找最大的Car
和foldr
,类型就变成了
foldr :: (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.
我试图找到列表的最大元素,其中元素是我自己创建的数据类型,使用折叠而不是递归地进行。但是我最终遇到错误 "couldn't match type"。由于我是 haskell 的新手,我无法理解问题并希望知道如何正确应用 foldr 函数。
我尝试获取最大的元素是这样的:
-- (foldr comparison (head list) (tail list))
无法编译。
我已经包括了 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
折叠 Car 列表后我的预期结果是获得 'largest car' ,这基本上意味着时间最长的汽车。但是由于类型错误,我最终遇到了编译错误。
问题是 comparison
的类型和定义。
首先,类型应该是 Car -> Car -> Car
:你取 两个 Car
个值和 return 个较大的值。
其次,您对 comparison
的定义尝试将 单个 参数匹配为一个元组,而不是两个单独的参数。删除括号和逗号。
comparison :: Car -> Car -> Car
comparison car1 car2 = if car1 > car2 then car1 else car2
(当然,comparison
只是max
限制在Car
而不是Ord a => a
。
comparison :: Car -> Car -> Car
comparison = max
而且,正如 Robin Zigmond 指出的那样,foldr comparison x
基本上是 maximum
的适当值 x
。)
考虑foldr
的简化类型。
foldr :: (a -> b -> b) -> b -> [a] -> b
这比您需要的要通用得多,因为您要处理所有汽车。也就是说找最大的Car
和foldr
,类型就变成了
foldr :: (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.