推断lambda表达式的类型

时间:2018-05-13 01:13:00

标签: haskell lambda types expression type-inference

给定具有以下类型的函数a:
    a :: x -> Bool
和以下类型的另一个功能b:
    b :: Bool -> y
我试图找出推断以下函数类型的步骤:
    c = \d -> d a b
有人可以请求帮助解释如何做到这一点,而不仅仅是通过ghc的:类型函数? 感谢

2 个答案:

答案 0 :(得分:2)

c = \d -> d a b的类型为c :: ((x -> Bool) -> (Bool -> y) -> t) -> t

其中d是一个接受(x -> Bool)(Bool -> y)并返回t类型值的函数。

所以c是一个函数,它接受d类型的函数并返回t类型的值

如果您的意思是c = \d -> d (a b),则类型将为c :: (Bool -> y) -> y

一些额外的解释。

要了解c,我们必须首先了解d的内容,以便我们查看c = \d -> d a b

我们看到\d -> d a b因此我们知道d的第一个参数是类型为a的函数(x -> Bool)。我们也知道d的第二个参数,它是类型b的函数(Bool -> y)。但是我们不知道它返回什么,因为这是Haskell必须返回的东西,所以我只是将t写成未知类型。 因此dd :: a -> b -> t

替换为ab类型,我们获得d :: (x -> Bool) -> (Bool -> y) -> t

现在对于cc是一个lambda,它接受一个我们可以推断出类型为d的值,并返回其输出。我们得到c :: d -> (d's output)

替换d类型,我们得到c :: ((x -> Bool) -> (Bool -> y) -> t) -> t

答案 1 :(得分:1)

我要采取的另一种方法是确保我在避免:t时获取特定lambda表达式所期望的类型签名是使用类型签名。

在这种情况下,x不受限制。

idFunction = \x -> x

如果我们想限制特定类型,我们可以直接注释x。 (这需要GHCi中的:set -XScopedTypeVariables或文件中的{-# LANGUAGE ScopedTypeVariables #-}

idFunction = \(x :: Int) -> x

或者我们可以添加类型签名

idFunction :: Int -> Int
idFunction = \x -> x

在您的示例中,您只有类型签名,但没有函数体。让我们添加一些简单的函数体,以便我们可以对编译器做一些事情,然后我们将尝试向c添加类型签名,以确认我们对类型应该是什么的信念。我们将从错误的类型签名开始。

a :: Int -> Bool
a x = x > 0

b :: Bool -> String
b y = show y

c :: ((Bool -> Bool) -> (Bool -> Bool) -> t) -> t
c = \d -> d a b

编译器会在c中找到一些错误:

<interactive>:10:17: error:
    • Couldn't match type ‘Bool’ with ‘Int’
      Expected type: Bool -> Bool
        Actual type: Int -> Bool
    • In the first argument of ‘d’, namely ‘a’
      In the expression: d a b
      In the expression: \ d -> d a b

<interactive>:10:19: error:
    • Couldn't match type ‘[Char]’ with ‘Bool’
      Expected type: Bool -> Bool
        Actual type: Bool -> String
    • In the second argument of ‘d’, namely ‘b’
      In the expression: d a b
      In the expression: \ d -> d a b

现在,如果我们给c正确的类型签名,它将编译

c :: ((Int -> Bool) -> (Bool -> String) -> t) -> t
c = \d -> d a b

通常没有任何理由可以避免:t。当你在GHCi中工作时,它是非常好的工具,但是当你在库中构建复杂的函数时,你不一定能访问:t,所以另一种方法是测试不同类型的签名,看看如何编译器做出反应。