dav*_*vik 3 haskell boolean-logic functor applicative
我是相对较新的haskell,我刚刚学习了Applicative Functors,我只使用仿函数和布尔函数为xor创建了这个代码.我想知道你们是否可以用仿函数提出一个更短的解决方案(我确信存在).
xor :: Bool->Bool->Bool
xor=(<$>) (not<$>) ((<*>).((((not<$>)<$>(&&))<$>)<$>((not<$>)<$>(&&)))<*>(||))
Run Code Online (Sandbox Code Playgroud)
我知道这可能不是很好的做法; 对我来说这更像是一个脑筋急转弯.
PS我希望这是允许的
这是一个你可以想象的手工编写的解决方案(阅读,有点指导!).正如@AJFarmar所说,我们可以写
xor a b = (a || b) && (not a || not b)
Run Code Online (Sandbox Code Playgroud)
我也将使用他所建议的改写,即a && b = not (not a || not b)
尽管他做的相反:
xor a b = (a || b) && not (a && b)
Run Code Online (Sandbox Code Playgroud)
您可以按照以下过程进行其他定义,但这个定义特别短.
现在,我们可以挑选出块a || b
和a && b
和,而不是他们的思维类型的值Bool
与环境a :: Bool
和b :: Bool
,并将其转化为我们把它们当作类型的值的形式Bool
有两个Applicative
"背景"的包装.因此(||) :: f (g Bool)
和(&&) :: f (g Bool)
,在f
和g
那些特定的Applicative
实例(->) Bool
.所以我们处于部分翻译状态
xor = (||) && not (&&)
Run Code Online (Sandbox Code Playgroud)
现在唯一的问题是中缀&&
和not
期望的纯Bool
值,但正在被双重包裹Bool
.所以我们将使用双重liftA*
应用程序解除它们.从而:
xor = liftA2 (liftA2 (&&)) (||) (liftA (liftA not) (&&))
Run Code Online (Sandbox Code Playgroud)
还有其他方法来拼写这个.我喜欢的名字(<$>)
来liftA
.此外,人们可以将双重包裹Applicative
的东西视为带有更复杂包装的单独包装的东西,因此:
xor = getCompose (liftA2 (&&) (Compose (||)) (not <$> Compose (&&)))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
651 次 |
最近记录: |