将 Haskell 中的函数转换为无点表示法
Transforming a function in Haskell to point free notation
我在纸上haskell有一个函数作为例子:
function2 a b c = (a * b) + c
并且我需要用无点表示法编写示例。我真的很不擅长使用无点风格,因为我发现它真的很混乱,没有适当的指导,所以我试了一下:
function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now
我不确定接下来应该出现什么,因为这是我能想到的这个例子的限制。希望能提供一些帮助。
--第二个例子:
function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)
您可以在此处应用 B 组合器(即 (f . g) x = f (g x)
):
function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator
确实类型是一样的:
> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a
> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b
我们通过以正确的顺序一个一个地提取参数来工作,最终得到
function2 a b c = (......) a b c
以便可以应用 eta 收缩 来摆脱显式参数,
function2 = (......)
我们的工具,我们可以双向应用,是
S a b c = (a c) (b c) = (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type
还有(f =<< g) x = f (g x) x = join (f . g) x
.
当我们使用 pointfree 一段时间后出现的更多有用模式是:
((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)
(更新。)在你的第二个例子开始附近有一个错误,使它之后的所有以下步骤无效:
function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section
是的,有些步骤是正确的。
我们可以继续:
function2 a b = (+) ((*) a b) [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]
这里是 "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c
运算符。它在功能上等同于:
((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)
请在此处查看 。
我在纸上haskell有一个函数作为例子:
function2 a b c = (a * b) + c
并且我需要用无点表示法编写示例。我真的很不擅长使用无点风格,因为我发现它真的很混乱,没有适当的指导,所以我试了一下:
function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c #operator sectioning
function2 a b c = (+) ((*) a b)c #operator sectioning once more
#I'm stuck here now
我不确定接下来应该出现什么,因为这是我能想到的这个例子的限制。希望能提供一些帮助。
--第二个例子:
function3 a b = a `div` (g b)
function3 a b = `div` a (g b) --operator sectioning
function3 a b = (`div` a) (g b) --parentheses
function3 a b = ((`div` a g).)b --B combinator
function3 a = ((`div` a g).) --eta conversion
function3 a = ((.)(`div` a g)) --operator sectioning
function3 a = ((.)flip(`div` g a))
function3 a = ((.)flip(`div` g).a) --B combinator
function3 = ((.)flip(`div` g)) --eta conversion (complete)
您可以在此处应用 B 组合器(即 (f . g) x = f (g x)
):
function2 a b c = (a * b) + c
function2 a b c = ((*) a b) + c -- operator sectioning
function2 a b c = (+) ((*) a b) c -- operator sectioning once more
= (+) (((*) a) b) c -- explicit parentheses
= ((+) . ((*) a)) b c -- B combinator
= ((.) (+) ((*) a)) b c -- operator sectioning
= ((.) (+) . (*)) a b c -- B combinator
确实类型是一样的:
> :t let function2 a b c = (a * b) + c in function2
let function2 a b c = (a * b) + c in function2
:: Num a => a -> a -> a -> a
> :t ((.) (+) . (*))
((.) (+) . (*)) :: Num b => b -> b -> b -> b
我们通过以正确的顺序一个一个地提取参数来工作,最终得到
function2 a b c = (......) a b c
以便可以应用 eta 收缩 来摆脱显式参数,
function2 = (......)
我们的工具,我们可以双向应用,是
S a b c = (a c) (b c) = (a <*> b) c
K a b = a = const a b
I a = a = id a
B a b c = a (b c) = (a . b) c
C a b c = a c b = flip a b c
W a b = a b b = join a b
U a = a a -- not in Haskell: `join id` has no type
还有(f =<< g) x = f (g x) x = join (f . g) x
.
当我们使用 pointfree 一段时间后出现的更多有用模式是:
((f .) .) g x y = f (g x y)
(((f .) .) .) g x y z = f (g x y z)
.....
((. g) . f) x y = f x (g y)
((. g) . f . h) x y = f (h x) (g y)
(更新。)在你的第二个例子开始附近有一个错误,使它之后的所有以下步骤无效:
function3 a b = a `div` (g b)
function3 a b = -- `div` a (g b) -- wrong syntax, you meant
div a (g b)
function3 a b = -- (`div` a) (g b) -- wrong; it is
(a `div`) (g b) --operator sectioning
function3 a b = ((a `div`) . g) b --B combinator
function3 a = (div a . g) --eta conversion; back with plain syntax
function3 a = (.) (div a) g --operator sectioning
function3 a = flip (.) g (div a) --definition of flip
function3 a = (flip (.) g . div) a --B combinator
function3 = (flip (.) g . div) --eta conversion
= (.) (flip (.) g) div --operator section
是的,有些步骤是正确的。
我们可以继续:
function2 a b = (+) ((*) a b) [eta-reduction]
function2 a = (+) . (*) a [using a dot, to eliminate the b]
function2 = ((.) . (.)) (+) (*) ["blackbird" operator to pass two parameters]
这里是 "blackbird operator" is a combination of three (.) :: (b -> c) -> (a -> b) -> a -> c
运算符。它在功能上等同于:
((.) . (.)) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
((.) . (.)) f g x y = f (g x y)
请在此处查看