Haskell - 如何使用(。)f g - 函数组合写两次函数

时间:2014-09-22 04:09:02

标签: haskell math lambda lambda-calculus

这是问题所在,我需要编写众所周知的两次函数

(twice= \x-> \x-> x) 

但这次使用(.)组合函数,例如(.) f g

我不知道如何解决它,因为我一开始就想过这样做:

(.) f g = (\x -> f (g x)) 

(g = f)所以就像这样

(.) f f = (\x -> f (f x))

但我有一个

  

"`f'"

的冲突定义

在GHCI上运行

那么,有什么建议吗?

1 个答案:

答案 0 :(得分:4)

我不知道除了解析输入之外你还得到了什么:

(.) f f = (\x -> f (f x))

但是您给出的定义:twice = \x -> \x -> x与使用某些内容无关"两次" - 的确如果你插入一些值:

twice a b
= (\x -> \x -> x) a b 
= (\x -> (\x -> x)) a b -- (rename the inner x)
= (\x -> (\y -> y)) a b
= ((\x -> (\y -> y)) a) b
= (\y -> y) b
= b

确实GHCi会告诉你同样的事情:

> let twice = \x -> \x -> x
> :t twice
twice :: t -> t1 -> t1
> twice "a" "b"
"b"

现在我猜你想要这样的东西:

let twice f x = f (f x)

例如:

> let twice f x = f (f x)
> twice (+1) 5
7

你可以看到twice (+1)增加2(或两次)。

现在如何使用(.)执行此操作? - 你的直觉是正确的:

> let twice f = f . f
> twice (+1) 5
7

关于模块

当你要求一个模块时 - 这会在我的系统中编译(并加载到GHCi中):

module Twice where

twice :: (a->a) -> a -> a
twice f = f . f

备注:

这只有在你从前奏(或GHC.Base)中加入(.)时才有效 - 我怀疑你有某种隐藏前奏的练习 - 在这种情况下你必须定义(.)首先为自己(很可能是另一种运动)

如果您需要自己实施:

(.) :: (b -> c) -> (a -> b) -> a -> c
(.) g f x = g (f x)