haskell - 比较 Haskell 中的函数

标签 haskell

有没有办法比较 Haskell 中的两个函数?

我的想法是答案是否定的,因为函数不会派生 Eq 类型类。但是我正在尝试编写一个非常微不足道的函数,这似乎是一种正常的事情:

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”函数作为运算符,它可以向前和向后工作。但是,我需要检查它是否不会超出枚举范围,否则会引发异常。

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

任何其他关于改进代码的指针也将不胜感激:)

感谢所有伟大的提示,这是我提出的解决方案(真的从每个答案中吸取了一点!):

编辑:下面的正确解决方案:
 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
                     _ -> []

测试:
*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]

最佳答案

无用的答案

没有也永远不会有一种方法来比较两个函数是否相等。有一个数学证明,一般来说这是不可能的。

“实用”方法要么取决于编译器的内部工作(例如,如果两个函数在内部由相同的内存地址表示,则它们是否相等),或者没有预期的帮助。
succ == (+1) 的预期结果是什么?让 succ == (+a) 中的 a == 1 怎么样?

我想不出一种方法来为总是有意义的函数定义 (==),我相信其他人也不能。

与问题无关的事情

类型签名缺少返回类型。

您的函数有 rank 2 类型,这不是标准的 Haskell 98,更重要的是,在这种情况下不是必需的。您不关心传入的函数是否可以处理任何 Enum 类型,您只关心它是否适用于 Rank:

search :: (Rank -> Rank) -> Card -> [Card] -> [Card]   -- much simpler.

我会尝试更频繁地使用案例,如果/那么更少。特别是,我会写:
case [ n | n <- list, rank n == op (rank x)] of
    [y] -> x : search op y list   -- length == 1
    _ -> []                       -- otherwise

我的真实答案

您的函数基本上只适用于 op 的两个不同值,但它的类型并没有这么说;这不适合我。

你可以用老式的方式来做:
data Direction = Succ | Pred deriving(Eq)

search :: Direction -> Card -> [Card] -> [Card]
search dir x list = if (dir == Succ && rank x == King) ...
    ... let op = case Direction of Succ -> succ ; Pred -> pred
        in ...

或者您可以使参数更通用,并传递一个可能会正常失败的函数(通过返回 Nothing):
maybeSucc x | x == maxBound = Nothing
            | otherwise = Just (succ x)

search :: (Rank -> Maybe Rank) -> Card -> [Card] -> [Card]
search op x list = case op (rank x) of
    Nothing -> []
    Just theRank -> case [ n | n <- list, rank n == theRank ] of ...

关于haskell - 比较 Haskell 中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4328620/

相关文章:

haskell - 通过 c2hsc 和 hsc2hs 连接 Haskell 中的 C 联合

haskell - 为什么我不能将两个阅读器堆叠在一起?

dictionary - Haskell map : Transform key and catch errors

c# - C# 中的 Monadic 编程

haskell - 是否可以使用 GHC 在 Windows 上构建 64 位 dll?

haskell - 在 Cabal (Haskell) 中连接构建工具

haskell - Haddock 文档中使用 unicode 字符

Haskell >.> 符号

haskell - ApplicativeDo 不使用测序

haskell - 查找函数的 GHC 程序集