推断 lambda 表达式的类型
Inferring type of lambda expression
给定一个具有以下类型的函数 a:
a :: x -> Bool
和以下类型的另一个函数 b:
b :: Bool -> y
我正在尝试找出推断以下函数类型的步骤:
c = \d -> d a b
有人可以帮助解释如何做到这一点,而不仅仅是通过 ghc 的 :type 函数吗?
谢谢
c = \d -> d a b
的类型将是 c :: ((x -> Bool) -> (Bool -> y) -> t) -> t
其中 d
是一个接受 (x -> Bool)
和 (Bool -> y)
和 return 类型值的函数 t
.
所以 c
是一个接受类型 d
和 return 类型值的函数 t
如果你的意思是 c = \d -> d (a b)
类型将是 c :: (Bool -> y) -> y
一些额外的解释。
要知道 c
我们必须先知道 d
做什么 所以我们看看 c = \d -> d a b
我们看到 \d -> d a b
,所以我们知道 d
的第一个参数是类型为 (x -> Bool)
的函数 a
。我们还知道d
的第二个参数,它是类型为(Bool -> y)
的函数b
。但是我们不知道它 return 是什么,因为这是 Haskell 它必须 return 一些东西,所以我只是将 t
写成未知类型。
所以 d
是 d :: a -> b -> t
.
代入 a
和 b
的类型,我们得到 d :: (x -> Bool) -> (Bool -> y) -> t
.
现在对于 c
,c
是一个 lambda,它接受一个我们可以推断类型为 d
的值,并且 return 是它的输出。所以我们得到 c :: d -> (d's output)
.
替换为 d
的类型,我们得到 c :: ((x -> Bool) -> (Bool -> y) -> t) -> t
另一种确保获得特定 lambda 表达式期望的类型签名同时避免 :t
的方法是使用类型签名。
在这种情况下,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
,因此另一种方法是测试不同的类型签名并查看如何编译器反应。
给定一个具有以下类型的函数 a:
a :: x -> Bool
和以下类型的另一个函数 b:
b :: Bool -> y
我正在尝试找出推断以下函数类型的步骤:
c = \d -> d a b
有人可以帮助解释如何做到这一点,而不仅仅是通过 ghc 的 :type 函数吗?
谢谢
c = \d -> d a b
的类型将是 c :: ((x -> Bool) -> (Bool -> y) -> t) -> t
其中 d
是一个接受 (x -> Bool)
和 (Bool -> y)
和 return 类型值的函数 t
.
所以 c
是一个接受类型 d
和 return 类型值的函数 t
如果你的意思是 c = \d -> d (a b)
类型将是 c :: (Bool -> y) -> y
一些额外的解释。
要知道 c
我们必须先知道 d
做什么 所以我们看看 c = \d -> d a b
我们看到 \d -> d a b
,所以我们知道 d
的第一个参数是类型为 (x -> Bool)
的函数 a
。我们还知道d
的第二个参数,它是类型为(Bool -> y)
的函数b
。但是我们不知道它 return 是什么,因为这是 Haskell 它必须 return 一些东西,所以我只是将 t
写成未知类型。
所以 d
是 d :: a -> b -> t
.
代入 a
和 b
的类型,我们得到 d :: (x -> Bool) -> (Bool -> y) -> t
.
现在对于 c
,c
是一个 lambda,它接受一个我们可以推断类型为 d
的值,并且 return 是它的输出。所以我们得到 c :: d -> (d's output)
.
替换为 d
的类型,我们得到 c :: ((x -> Bool) -> (Bool -> y) -> t) -> t
另一种确保获得特定 lambda 表达式期望的类型签名同时避免 :t
的方法是使用类型签名。
在这种情况下,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
,因此另一种方法是测试不同的类型签名并查看如何编译器反应。