比较 Haskell 中的函数 [英] Comparing functions in Haskell
问题描述
有没有办法比较 Haskell 中的两个函数?
Is there any way to compare two functions in Haskell?
我的想法是答案是否定的,因为函数不会派生 Eq 类型类.但是,我正在尝试编写一个非常简单的函数,这似乎是一件很正常的事情:
My thought is that the answer is no since functions would not derive the Eq type class. However I'm trying to write a pretty trivial function and it seems like a normal sort of thing to do:
search :: ((Enum a) => a -> a) -> Card -> [Card]
search op x list = if (op == succ && rank x == King) ||
(op == pred && rank x == Ace)
then []
else let c = [ n | n <- list, rank n == op (rank x)]
in if length c == 1
then x : search op (head c) list
else []
错误信息:
No instance for (Eq (Rank -> Rank))
arising from a use of `=='
基本上,它向上或向下搜索卡片列表,寻找与来自 x 的下一个或上一个排名卡片匹配的卡片,构建一个列表.通过将 'pred' 或 'succ' 函数作为运算符,它可以向前和向后工作.但是,我需要检查它是否没有超出枚举范围,否则会引发异常.
Basically it either searches up or down a list of cards looking for a match with either the next or previous ranked card from x, building a list. By taking the 'pred' or 'succ' function as an operator it works both forwards and backwards. However, I need to check that it doesn't go out of bounds on the enum otherwise it throws an exception.
所以我正在寻找一种方法来防止异常或解决这个问题!
So I'm looking for a way to prevent the exception or solve this problem!
关于改进代码的任何其他指针也将不胜感激:)
Any other pointers on improving the code would also be appreciated :)
感谢所有很棒的提示,这是我想出的解决方案(确实从每个答案中提取了一些内容!):
Thanks for all the great tips, this is the solution I have come up with (taken bits from every answer really!):
下面的正确解决方案:
maybeSucc x | x == maxBound = Nothing
| otherwise = Just (succ x)
maybePred x | x == minBound = Nothing
| otherwise = Just (pred x)
-- takes a list of cards which have a rank one op than x
-- only if there is exactly one is it sequential, otherwise end matching
search :: (Rank -> Maybe Rank) -> Rank -> [Card] -> [Card]
search op x list = case filter (
-> Just (rank n) == op x) list of
[y] -> y : search op (rank y) list
_ -> []
测试:
*Main> let cards = [Card Ace Heart, Card Two Club, Card Three Spade, Card Five Club, Card Four Diamond]
*Main> search maybeSucc Two cards
[Three of Spades,Four of Diamonds,Five of Clubs]
*Main> search maybePred Three cards
[Two of Clubs,Ace of Hearts]
推荐答案
1) 你的 op
过于笼统.无论 rank (undefined :: Card)
是什么类型,您都只会将它用于 Card,因此只需将其设为 RankThing ->RankThing
.此外,您的函数类型签名缺少返回值类型.
1) Your op
is overly general. You'll only be using it for Card whatever type rank (undefined :: Card)
is, so just make it RankThing -> RankThing
. Also, your function type signature is missing a return value type.
2) 一个预期用途的示例看起来像 search succ Ace xs
,但这相当笨拙,两个处理边界的辅助函数怎么样:
2) An example intended use looks like it would be search succ Ace xs
, but that's rather clumsy, how about two auxillary functions that handle the bounds:
searchUp King _ = []
searchUp x ys = search succ x ys
searchDown Ace _ = []
searchDown x ys = search pred x ys
这对您的用户来说可能更好读,并且无需检查操作
This might read better for your users and avoid the need to check the operation
3) 如果您真的想检查执行了什么操作,并且知道该操作将是两种可能性之一,那么您可以命名该操作或使用已知答案测试 (KAT) 对其进行测试.例如:
3) if you really want to check what operation is performed, and know the operation will be one of two possibilities, then you can either name the operation or test it with a known answer test (KAT). For example:
data Operation = Succ | Pred
search :: Operation -> Card -> [Card] -> []
search Succ King _ = []
search Succ x ys = search' succ x ys
search Pred Ace _ = []
search Pred x ys = search' pred x ys
和 KAT 解决方案(相当蹩脚,imo):
And the KAT solution (rather lame, imo):
search op x ys
| op Five == Four && rank x == Ace = []
| op Five == Six && rank x == King = []
| otherwise = ...
这篇关于比较 Haskell 中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!