gpt4 book ai didi

haskell - 推导出这个无点代码的步骤是什么?

转载 作者:行者123 更新时间:2023-12-04 13:22:54 25 4
gpt4 key购买 nike

我正在查看一些代码并遇到以下 gem,我敢打赌它是 pointfree 的复制粘贴输出:

(我认为对于这个特定问题,以下内容比通常的 foo/bar 更合适:P)

import Control.Monad (liftM2)

data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show

placeBattleship :: Int -> Int -> Battleship
placeBattleship x' y' = Battleship { x = x', y = y' }

coordinates :: Battleship -> (Int, Int)
coordinates = liftM2 (,) x y

有人能解释一下简化所需的步骤吗:(i) coordinates b = (x b, y b)至: (ii) coordinates = liftM2 (,) x y ?特别是,我对 liftM2 的使用有点困惑。因为我什至不知道背后潜伏着一个单子(monad)。

我知道(i)也可以表示为: coordinates s = (,) (x s) (y s)但我不确定在哪里/如何进行。

附言以下是我怀疑它来自 pointfree 的原因(输出来自 GHCI:pl 别名为 pointfree ):
λ: :pl coordinates s = (x s, y s)
coordinates = liftM2 (,) x y

最佳答案

这利用了 Monad (->) r 的实例,也称为“阅读器单子(monad)”。这是从特定类型到 a 的函数的单子(monad)。 . (看看 here 了解它为什么存在的动机。)

要查看它如何用于各种功能,请替换 m(r ->m a .例如,如果我们只做 liftM ,我们得到:

liftM :: (a -> b) -> (m a -> m b)
liftM :: (a -> b) -> ((r -> a) -> (r -> b))
:: (a -> b) -> (r -> a) -> (r -> b) -- simplify parentheses

...这只是功能组合。整洁的。

我们可以为 liftM2 做同样的事情:
liftM2 :: (a -> b -> c) -> m a -> m b -> m c
liftM2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)

所以我们看到的是一种将两个单参数函数与双参数函数组合在一起的方法。这是一种将普通函数组合推广到多个参数的方法。我们的想法是我们创建一个函数,该函数采用单个 r通过将其传递给两个单参数函数,将两个参数传递给双参数函数。所以如果我们有 f :: (r -> a) , g :: (r -> b)h :: (a -> b -> c) ,我们产生:
\ r -> h (f r) (h r)

现在,这如何应用于您的代码? (,)是两个参数的函数, xyBattleship -> Int 类型的单参数函数(因为这就是字段访问器的工作方式)。考虑到这一点:
liftM2 (,) x y = \ r -> (,) (x r) (y r)
= \ r -> (x r, y r)

一旦你内化了像这样的多函数组合的想法,像这样的无点代码变得更具可读性——无需使用无点工具!在这种情况下,我认为非无点版本仍然更好,但无点版本本身并不可怕。

关于haskell - 推导出这个无点代码的步骤是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27028986/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com