没有那个确切的类型签名,不。例如,如果您选择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)]
列表,这似乎效率低下。
结论
尽管我相信没有与您指定的类型完全相同的有用功能,但有多种方法可以解决您所说的问题。这是一个有趣的问题,谢谢。