【问题标题】:Haskell - How to write (.) f f = (\x -> f (f x))Haskell - 如何写 (.) f f = (\x -> f (f x))
【发布时间】:2014-09-22 03:20:28
【问题描述】:

我需要编写一个要在 GHCi 上运行的模块,并将函数组合到相同的函数。这个(经典的fog(x) = f(g(x)))运行:

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

当我尝试这样写时出现问题

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

GHCi 说:

"Conflicting definitions for `f'
 Bound at: Lab1.hs:27:9
           Lab1.hs:27:12"

第 27:9 行出现 f,第 27:12 行再次出现 f。

为什么 Haskell 不理解 (.) f f = (\x -> f (f x))

【问题讨论】:

  • 您是否尝试对两个参数相等的情况进行模式匹配?因为在这种情况下,您不仅会遇到语法问题(需要为不同的参数使用不同的名称),还会遇到概念问题(函数的相等性 - 通常 - 无法确定)。
  • 你想要twice f = \x -> f (f x)吗?

标签: haskell math ghci calculus


【解决方案1】:

在 Haskell 中,函数的参数必须具有唯一的名称。不允许对另一个参数使用相同的名称。这是因为

foo x y = ...    ===    foo = (\x-> (\y-> ...))

如果将y 替换为x,则第二个x 只会遮蔽... 正文中的第一个:将无法从那里引用第一个x

你可以定义twice f x = f (f x):

前奏曲> :t 两次
两次 :: (t -> t) -> t -> t
前奏>两次(+1)4
6


或者,f (f x) = (.) f f x = join (.) f x:

Prelude Control.Monad> :t join (.)
加入 (.) :: (b -> b) -> b -> b

joinControl.Monad 中定义。对于函数,它认为join g x = g x x。它也被称为W combinator

例如print $ join (.) (+1) 4prints 6.

【讨论】:

    【解决方案2】:

    正如错误消息所述,您在定义 (.) f f = (\x -> f (f x)) 中对 f 的定义存在冲突。您将名称f 绑定到(.) 的第一个和第二个参数,因此ghci 在评估表达式f x 时不知道使用哪个参数。

    使用模式(.) f g 定义(.),然后使用恰好相同的两个参数调用它并没有错。

    【讨论】:

    • 但是我需要像 (.) f f 这样写,我知道 (.) f g 是正确的,因为我在 GHCI 上运行和探测。我认为它必须是一种正确书写 (.) f f 的形式,对我来说这是一个语法问题。
    • user3421938:不,你不能这样做:λ let doesThisWork nope nope = nope :44:18: 'nope' 的定义冲突 绑定于::44:18 -21 :44:23-26 在“doesThisWork”等式中
    猜你喜欢
    • 1970-01-01
    • 2021-03-15
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多