我正在尝试使用我自己的类型类 Max 和 List 实例来实现最大迭代器(就像在 Ruby 中一样)。但我无法使类型正确。这是否意味着“b”不能与“a”相同?但我想通过其自身值(value)获得最大项目是什么?
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]
最佳答案
I cannot make the type correct. Does that mean
b
cannot be same asa
?
它可以,但两者本身并不相同。
但是,问题并不是由使用 c_max
引起的在 main
功能。这里基本上有两个问题。
首先,您从 a
执行映射至b
,但你没有限制b
为 Ord
实例的类型。因此,我们无法比较两者b
来决定什么b
是最大的。因此我们应该添加 Ord b
类型约束:
class Max t where
c_max :: <b>Ord b =></b> (a -> b) -> t a -> a
在您的 instance Max []
中你的max
比较两个b
s,并返回最大的b
。但鉴于您的类型签名,您希望返回相应的 a
。我们可以通过以下方式实现:
instance Max [] where
c_max f [a] = a
c_max f (x:xs) | <b>f x > f mx</b> = 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
适用于 Foldable
的函数s。因此,这将与列表一起使用,即 Tree
等等。我们可以定义 maximumBy
或类似的在 Foldable
上运行的东西同样,通过稍微改变“折叠功能”。
关于haskell - 在 Haskell 中使用自己的类型类实现最大迭代器时无法遵循类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58361018/