在 Haskell 中使用自己的类型类实现最大迭代器时无法组合类型



我正在尝试通过使用我自己的类型类Max和List实例来实现max迭代器(如在Ruby中(。但是我无法使类型正确。这是否意味着"b"不能与"a"相同?但是我想通过自己的价值获得最大项目是什么?

class Max t where
c_max :: (a->b) -> t a -> a
instance Max [] where
c_max f [a] = a
c_max f (x:xs) = max (f x) (c_max f xs)
main = putStrLn $ show $ c_max (x-> x) [1,2]

我无法使类型正确。这是否意味着b不能与a相同?

它可以,但两者本身并不相同。

但是,在main函数中使用c_max不会引起此问题。这里基本上有两个问题。

首先,执行从ab的映射,但未将b限制为作为Ord实例的类型。因此,我们无法比较两个b来确定哪个b最大。因此,我们应该添加一个Ord b类型约束:

class Max t where
c_max ::Ord b =>(a -> b) -> t a -> a

instance Max []中,max比较两个b,并返回最大的b。但是给定您的类型签名,您希望返回相应的a。我们可以通过以下方式实现这一点:

instance Max [] where
c_max f [a] = a
c_max f (x:xs) |f x > f mx= x
| otherwise = mx
where mx = c_max f xs

例如:

Prelude> putStrLn $ show $ c_max (x-> x) [1,2]
2

以上不是最有效的实现,因为我们在这里将为每个项目多次计算f x。我将其作为进一步优化的练习。

请注意,在Haskell中,有一个maximum :: (Foldable f, Ord a) => f a -> a函数适用于Foldables。因此,这将适用于列表、Tree等。人们可以通过稍微改变"折叠函数"来定义一个maximumBy或类似的东西,也可以在Foldable上运行。

最新更新