在 Haskell 中使“A || B && C”无点

Dav*_*hez 2 haskell pointfree applicative

我正在 Haskell 中处理一个简单的闰年练习,我想让我的解决方案无点。从此开始:

isLeapYear :: Integer -> Bool
isLeapYear year = divisibleBy 400 year || divisibleBy 4 year && not (divisibleBy 100 year)
  where
    divisibleBy m y = (== 0) $ flip mod m y
Run Code Online (Sandbox Code Playgroud)

我试着使用liftA3,与函数做(x || (y && z))下面这个,但测试没有完成,我不知道为什么。

那么,我有3个问题:

  • 您对我如何实现这一目标有任何指示吗?
  • 在我的第一个解决方案中,是什么阻止divisibleBy了无点?(如果我删除参数,类型检查器会抱怨)
  • 正如我之前提到的,我尝试了类似的东西liftA3 (\x y z -> x || (y && z)) (divisibleBy 400) (divisibleBy 4) (indivisibleBy 100),但测试挂起。为什么会这样?我不明白如何liftA3运作。

非常感谢你的帮助。

Lyn*_*ynn 5

在我的第一个解决方案中,是什么阻止了 divisibleBy 成为无点?(如果我删除参数,类型检查器会抱怨)

您可能认为这些是等效的(flipmod为了简单起见,我将其写为一个函数):

divisibleBy  m y = (== 0) $ flipmod m y
divisibleBy'     = (== 0) . flipmod
Run Code Online (Sandbox Code Playgroud)

但实际上,divisibleBy'现在是一个(无效)函数,它接受一个参数x然后与flipmod x零进行比较:

    ((==0) . flipmod) 5
?   (==0) (flipmod 5)
?   flipmod 5 == 0
Run Code Online (Sandbox Code Playgroud)

比较函数 ( flipmod 5) 和数字肯定不好。

你需要写一些更复杂的东西,即:

    ((==0) . flipmod) 5
?   (==0) (flipmod 5)
?   flipmod 5 == 0
Run Code Online (Sandbox Code Playgroud)

所以现在,正确地:

    divisibleBy 5 6
?   (((== 0) .) (flipmod 5)) 6
?   ((== 0) . flipmod 5) 6
?   (== 0) (flipmod 5 6)
?   flipmod 5 6 == 0
Run Code Online (Sandbox Code Playgroud)

这种构造(f.).g也可以写成((.).(.)) f g,并且该运算符有时称为dot。我不认为写这样的东西是一个很好的主意,但它可能会回答你的问题。


测试挂起。为什么会这样?

我不知道。你可能需要在这里提供一个mcve,因为这对我来说是一个完整的程序:

divisibleBy = ((== 0) .) . flipmod
Run Code Online (Sandbox Code Playgroud)