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

查看:103
本文介绍了比较Haskell中的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么办法可以比较Haskell中的两个函数吗?



我认为答案是否定的,因为函数不会派生出Eq类型的类。然而,我试图写一个非常简单的函数,它看起来像一个正常的事情:

  search :: ((Enum a)=> a  - > a) - >卡 - > [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 c == 1
then x:search op(head c)list
else []

错误讯息:

 没有使用'=='引起的(Eq(Rank  - > Rank))
的实例

基本上,它可以上下搜索一张卡片列表,查找与x中的下一张或上一张排名卡片相匹配的卡片,并建立一个列表。通过将'pred'或'succ'功能作为运营商,它可以向前或向后运行。但是,我需要检查它不会超出枚举的范围,否则会引发异常。



所以我正在寻找一种方法来防止例外或解决这个问题!



改善代码的任何其他指针也会被赞赏:)

谢谢对于所有伟大的提示,这是我提出的解决方案(从每个答案真的!):

编辑:正确的解决方案如下:

  maybeSucc x | x == maxBound = Nothing 
|否则= Just(succ x)
maybePred x | x == minBound = Nothing
|否则= Just(pred x)

- 获得一个排名为x的操作符的列表,而不是x
- 仅当其中有一个是连续的时,否则结束匹配
search ::(等级 - >可能等级) - >排名 - > [卡片] - > [card]
search op x list = case filter(\\\
- > Just(rank n)== op x)
[y] - > y:搜索op(等级y)列表
_ - >测试:





$ p

测试: > *主>让卡= [卡王牌心,卡两俱乐部,卡三锹,卡五俱乐部,卡四钻]

* Main>搜索maybeSucc两张牌

[三个黑桃,四个钻石,五个俱乐部]

* Main>搜索maybePred三张卡片

[两个俱乐部,一张心爱]


解决方案

1)您的 op 过于笼统。无论是 rank(undefined :: Card)是什么类型,只需将它用于 Card 即可,因此只需将 RankThing - > RankThing 。此外,您的函数类型签名缺少返回值类型。



2)示例用途看起来像是 search succ Ace xs ,但这很笨拙,如何处理边界的两个辅助函数:

  searchUp King _ = [] 
searchUp x ys =搜索succ x ys

searchDown Ace _ = []
searchDown x ys =搜索pred x ys

这对您的用户来说可能会更好,并且避免检查操作的必要性

3 )如果您确实想要检查执行的操作,并且知道该操作将是两种可能性之一,那么您可以命名该操作或使用已知的答案测试(KAT)对其进行测试。例如:

  data Operation = Succ | Pred 

search ::操作 - >卡 - > [卡片] - > []
搜索Succ King _ = []
搜索Succ x ys =搜索'succ x ys
搜索Pred Ace _ = []
搜索Pred x ys =搜索'pred x ys

以及KAT解决方案(相当跛脚,imo):

 搜索操作x ys 
| op Five == Four&& rank x == Ace = []
| op五==六&& rank x == King = []
|否则= ...


Is there any way to compare two functions in Haskell?

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 []

Error message:

No instance for (Eq (Rank -> Rank))
      arising from a use of `=='

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!):

EDIT: Correct solution below:

 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 (\n -> Just (rank n) == op x) list of
                    [y] -> y : search op (rank y) list
                     _ -> []

Test:

*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) 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) 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) 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

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天全站免登陆