在 Haskell 中使 "A || B && C" 无积分
Make "A || B && C" point-free in Haskell
我正在 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
我尝试使用 liftA3
,在 this 之后执行 (x || (y && z))
的函数,但测试没有完成,我不知道为什么。
那么,那么,我有3个问题:
- 关于我如何实现这一点,您有任何指示吗?
- 在我的第一个解决方案中,是什么阻止了
divisibleBy
无积分? (如果我删除参数,Typechecker 会抱怨)
- 正如我之前提到的,我尝试了类似
liftA3 (\x y z -> x || (y && z)) (divisibleBy 400) (divisibleBy 4) (indivisibleBy 100)
的方法,但测试挂起。为什么会这样?我不明白 liftA3
是如何工作的。
非常感谢您的帮助。
In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
您可能认为它们是等价的(为了简单起见,我将 flipmod
写成一个函数):
divisibleBy m y = (== 0) $ flipmod m y
divisibleBy' = (== 0) . flipmod
但实际上,divisibleBy'
现在是一个(无效的)函数,它接受一个参数 x
,然后将 flipmod x
与零进行比较:
((==0) . flipmod) 5
→ (==0) (flipmod 5)
→ flipmod 5 == 0
比较一个函数(flipmod 5
)和一个数字肯定不行。
你需要写一些更复杂的东西,即:
divisibleBy = ((== 0) .) . flipmod
所以现在,正确地:
divisibleBy 5 6
→ (((== 0) .) (flipmod 5)) 6
→ ((== 0) . flipmod 5) 6
→ (== 0) (flipmod 5 6)
→ flipmod 5 6 == 0
这个结构 (f.).g
也可以写成 ((.).(.)) f g
,那个运算符有时被称为 dot
。我不认为写这样的东西是个好主意,但它可能会回答你的问题。
The tests hang. Why does that happen?
我不知道。您可能需要在此处提供一个 mcve,因为作为一个完整的程序,这对我来说效果很好:
import Control.Applicative
isLeapYear :: Integer -> Bool
isLeapYear = liftA3 (\x y z -> x || (y && z))
(divisibleBy 400)
(divisibleBy 4)
(not . divisibleBy 100)
where
divisibleBy m y = (== 0) $ flip mod m y
main = print (filter isLeapYear [1850..1950])
我正在 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
我尝试使用 liftA3
,在 this 之后执行 (x || (y && z))
的函数,但测试没有完成,我不知道为什么。
那么,那么,我有3个问题:
- 关于我如何实现这一点,您有任何指示吗?
- 在我的第一个解决方案中,是什么阻止了
divisibleBy
无积分? (如果我删除参数,Typechecker 会抱怨) - 正如我之前提到的,我尝试了类似
liftA3 (\x y z -> x || (y && z)) (divisibleBy 400) (divisibleBy 4) (indivisibleBy 100)
的方法,但测试挂起。为什么会这样?我不明白liftA3
是如何工作的。
非常感谢您的帮助。
In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
您可能认为它们是等价的(为了简单起见,我将 flipmod
写成一个函数):
divisibleBy m y = (== 0) $ flipmod m y
divisibleBy' = (== 0) . flipmod
但实际上,divisibleBy'
现在是一个(无效的)函数,它接受一个参数 x
,然后将 flipmod x
与零进行比较:
((==0) . flipmod) 5
→ (==0) (flipmod 5)
→ flipmod 5 == 0
比较一个函数(flipmod 5
)和一个数字肯定不行。
你需要写一些更复杂的东西,即:
divisibleBy = ((== 0) .) . flipmod
所以现在,正确地:
divisibleBy 5 6
→ (((== 0) .) (flipmod 5)) 6
→ ((== 0) . flipmod 5) 6
→ (== 0) (flipmod 5 6)
→ flipmod 5 6 == 0
这个结构 (f.).g
也可以写成 ((.).(.)) f g
,那个运算符有时被称为 dot
。我不认为写这样的东西是个好主意,但它可能会回答你的问题。
The tests hang. Why does that happen?
我不知道。您可能需要在此处提供一个 mcve,因为作为一个完整的程序,这对我来说效果很好:
import Control.Applicative
isLeapYear :: Integer -> Bool
isLeapYear = liftA3 (\x y z -> x || (y && z))
(divisibleBy 400)
(divisibleBy 4)
(not . divisibleBy 100)
where
divisibleBy m y = (== 0) $ flip mod m y
main = print (filter isLeapYear [1850..1950])