没有那个确切的类型签名,不。例如,如果您选择type b = Double->Double并且您的函数[b]->b是foldr (.) id,那么您的多态函数q 不能使用那里产生的值从对中进行选择,但我认为这会将您的问题误解为寻求特定类型的 sig,而不是提升/提升选择方式从元素到对。
解决原始选择问题
如果您的原始函数仅用于从列表中选择一个元素,您可以告诉 Haskell 如何在两者之间进行选择。
这个解决方案是安全的,因为它通过使用辅助函数强制使用原始列表或后备元素中的选择b -> b -> Bool,其中True表示您更喜欢第一个参数。
我们可以使用它从一对中进行选择:
selectPair :: (a -> a -> Bool) -> (a,c) -> (a,c) -> (a,c)
selectPair f (a,c) (a',c')
| f a a' = (a,c)
| otherwise = (a',c')
然后折叠以从列表中选择:
selectList :: (a -> a -> Bool) -> (a,c) -> [(a,c)] -> (a,c)
selectList f = foldr (selectPair f)
请注意,这不需要 type 上的任何实例a,因此可能是您在一般设置中所需要的。
解决最大问题
当然(b -> b -> Bool)感觉很像>来自一个Ord实例,并且您的示例使用了一个建议最大值的函数,但是如果您有一个 Ord 实例,那么使用 importData.List和Data.Function执行将是最简单的
safePairMaximum :: Ord b => (a, b) -> [(a, b)] -> (a, b)
safePairMaximum m bs = maximumBy (compare `on` snd) $ m:bs
这是hammar 解决方案的一部分的更基本、更不酷的版本。
也许你被 [b]->b 卡住了,但是在 b 上确实有相等性
这与我认为合理的类型签名一样接近,同时仍然解决了您陈述的问题:如果使用选择功能::[b]->b至关重要,那么您至少需要一个Eq上下文:
chooseLike :: Eq b => (a, b) -> ([b] -> b) -> ([(a, b)] -> (a, b))
chooseLike m selectb pairs = let wanted = selectb $ map snd pairs in
case filter ((==wanted).snd) pairs of
[] -> m
(p:_) -> p
(您当然可以Eq用参数替换上下文(b -> b -> Bool),这一次表示相等。)
这并不理想,因为您将[b]列表单独遍历到[(a,b)]列表,这似乎效率低下。
结论
尽管我相信没有与您指定的类型完全相同的有用功能,但有多种方法可以解决您所说的问题。这是一个有趣的问题,谢谢。