比较 Haskell 中的函数 [英] Comparing functions in Haskell

查看:20
本文介绍了比较 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆