Haskell:Lambda函数 - 错误 - 逃避它们的范围

时间:2017-12-11 05:56:00

标签: haskell lambda

我定义了以下模块:

module ComplexCompose where

isEven x =
 if x `rem` 2 == 0 then
  (True, "Is Even")
 else
  (False, "Is Odd")


negateIt x = ( not x, "negated")



composer x =
 (c, b ++ ", " ++ d) where (a,b) = isEven x
                           (c,d) = negateIt a

以下对作曲家的修改工作正常:

composerV1 x f g =
 (c, b ++ ", " ++ d) where (a,b) = f x
                           (c,d) = g a

我想让作曲家函数返回一个组成f和g的lamda。我试过这个:

composerV2 f g =
     \x -> (c, b ++ ", " ++ d) where (a,b) = f x
                                     (c,d) = g a

它不起作用。这个版本有什么问题?

编译器输出:

 • Couldn't match expected type ‘t0 -> (t5, t4)’
                  with actual type ‘t3’
        because type variables ‘t4’, ‘t5’ would escape their scope
      These (rigid, skolem) type variables are bound by
        the inferred type of
        a :: t5
        b :: t4
        at complex-compose.hs:27:34-44
    • In the expression: f x
      In a pattern binding: (a, b) = f x
      In an equation for ‘c4’:
          c4 f g
            = \ x -> (c, b ++ ", " ++ d)
            where
                (a, b) = f x
                (c, d) = g a
    • Relevant bindings include
        a :: t5 (bound at complex-compose.hs:27:35)
        b :: t4 (bound at complex-compose.hs:27:37)
        f :: t3 (bound at complex-compose.hs:26:4)
        c4 :: t3 -> (t2 -> (t1, [Char])) -> t -> (t1, [Char])
          (bound at complex-compose.hs:26:1)

顺便说一句,以下简单功能有效:

fn f g =      \ x = g(f x)

1 个答案:

答案 0 :(得分:0)

如果我没有在左侧写composerV2

x会为我打字:

composerV2 f g x =
     (c, b ++ ", " ++ d) where (a,b) = f x
                               (c,d) = g a

问题是在where子句中,标识符x实际上并不在范围内。错误消息有点令人困惑,但如果添加类型签名则会变得精确,这无论如何都是很好的做法。

或者,您可以使用let绑定。

请注意,composerV2 f g = let ... in \x -> ...composerV2 f g x = ...在语义上是相同的,因为您可以部分应用第二个版本。

编辑:使用let绑定的版本如下所示:

composerV2' f g = \x ->
  let (a,b) = f x
      (c,d) = g a
  in (c, b ++ ", " ++ d)