Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 推导这个无点代码的步骤是什么?_Haskell_Pointfree_Lifting - Fatal编程技术网

Haskell 推导这个无点代码的步骤是什么?

Haskell 推导这个无点代码的步骤是什么?,haskell,pointfree,lifting,Haskell,Pointfree,Lifting,我在查看一些代码时发现了以下gem,我敢打赌它是pointfreeoutput的复制粘贴: (我认为对于这个特殊的问题,以下内容比通常的foo/bar更合适:p) 有人能解释一下简化的步骤吗?(i)坐标b=(xb,yb)(ii)坐标=liftM2(,)xy尤其是,我对liftM2的用法有点困惑,因为我甚至没有意识到背景中隐藏着一个单子 我知道(I)也可以表示为:坐标s=(,)(xs)(yss),但我不确定在哪里/如何继续 另外,以下是我怀疑它来自pointfree(输出来自GHCI,:pl别名

我在查看一些代码时发现了以下gem,我敢打赌它是
pointfree
output的复制粘贴:

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

有人能解释一下简化的步骤吗?

(i)
坐标b=(xb,yb)


(ii)
坐标=liftM2(,)xy


尤其是,我对
liftM2
的用法有点困惑,因为我甚至没有意识到背景中隐藏着一个单子

我知道(I)也可以表示为:
坐标s=(,)(xs)(yss)
,但我不确定在哪里/如何继续


另外,以下是我怀疑它来自
pointfree
(输出来自
GHCI
:pl
别名为
pointfree
):


monad
liftM2
正在这里工作,这里是monad
(>)a
函数。这相当于
读取器
monad,正如您以前可能看到的那样

回想一下
liftM2
的定义:

liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
liftM2 f ma mb = do
    a <- ma
    b <- mb
    return $ f a b
liftM2 :: (a -> b -> c) -> m a -> m b -> m c
liftM2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)
由于
x,y::战列舰->Int
相当于
(->)战列舰)Int
,那么
m~(>)战列舰
。函数monad定义为

instance Monad ((->) a) where
    return x = const x
    m >>= f = \a -> f (m a) a
从本质上讲,monad函数允许您从多个函数中提取输出,前提是它们都具有相同的输入。一个更清楚的例子可能是

test = do
    a <- (^2)
    b <- (^3)
    c <- (^4)
    d <- show
    return (a, b, c, d)

> test 2
(4, 8, 16, "2")
test=do

a这利用了
(>)r
Monad
实例,也称为“reader Monad”。这是从特定类型到
a
的函数单子。(首先看看它为什么存在的动机。)

要查看它如何用于各种功能,请在
ma
中将
m
替换为
(r->
。例如,如果我们只执行
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 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
liftM2 f ma mb = do
    a <- ma
    b <- mb
    return $ f a b
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)
现在,这如何应用于您的代码?
(,)
是双参数函数,
x
y
Battleship->Int
类型的单参数函数(因为字段访问器就是这样工作的)。请记住:

liftM2 (,) x y = \ r -> (,) (x r) (y r)
               = \ r -> (x r, y r)

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

你可以很容易地重写

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

placeBattleship :: Int -> Int -> Battleship
placeBattleship x y = Battleship x y

coordinates :: Battleship -> (Int, Int)
coordinates  (Battleship x y) = (x, y)
这不是无点风格,但相当简单

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

placeBattleship :: Int -> Int -> Battleship
placeBattleship x y = Battleship x y

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