函数 g = (.).(.) 的类型是什么?
What is the type of the function g = (.).(.)?
答案是:(a -> b) -> (c -> d -> a) -> c -> d -> b
但是我不知道怎么去。
(.)
具有类型 (b -> c) -> ((a -> b) -> (a -> c))
。为了清楚起见,我特意添加了一些括号。在表达式 (.) . (.)
中有三个 (.)
的实例,因此使用不同字母的三个版本的类型会很方便。
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
– (.)
的第一个实例:(.)
.
(.)
(.) :: (e -> f) -> ((d -> e) -> (d -> f))
– (.)
的第二个实例:(.)
. (.)
(.) :: (h -> i) -> ((g -> h) -> (g -> i))
– (.)
的第三个实例:(.) .
(.)
(.) . (.)
等价于 ((.) (.)) (.)
,它将 (.)
应用到 (.)
,然后将第一个应用的结果应用到 (.)
。
申请一审到二审
将参数类型 ((e -> f) -> ((d -> e) -> (d -> f))
) 与 (.)
(b -> c
) 的输入类型相匹配:
b = (e -> f)
c = ((d -> e) -> (d -> f))
然后将 (.)
((a -> b) -> (a -> c)
) 的结果类型中的类型变量替换为来自参数的匹配项:
(.) (.) :: (a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f)))
将第一次申请的结果应用于第三次
将参数类型 ((h -> i) -> ((g -> h) -> (g -> i))
) 与 (.) (.)
(a -> (e -> f)
) 的输入类型相匹配:
a = (h -> i)
e = (g -> h)
f = (g -> i)
然后将 (.) (.)
(a -> ((d -> e) -> (d -> f))
) 的结果类型中的类型变量替换为来自参数的匹配项:
(.) (.) (.) :: (h -> i) -> ((d -> (g -> h)) -> (d -> (g -> i)))
这与您在问题中的类型相同,只是括号更多,字母不同。如果我删除不必要的括号,结果如下:
(.) (.) (.) :: (h -> i) -> (d -> g -> h) -> d -> g -> i
它有什么作用?它接受两个 d
和 g
类型的参数,对它们应用 d -> g -> h
类型的函数,然后对结果应用 h -> i
类型的函数。
类型(.) :: (b->c) -> (a->b) -> (a->c)
表示
g :: a -> b
f :: d -> c
-------------------- d ~ b
f . g :: a -> c
因此
(.) :: (b->c) -> ((a->b) -> (a->c))
(.) :: ( s -> r ) -> (t->s) -> (t->r)
-------------------------------------------------------------
(.) . (.) :: (b->c) -> (t->s) -> (t->r)
~ (b->c) -> (t->a->b) -> t->a->c
这是有道理的,因为
((.) . (.)) f g x y =
= (.) ((.) f) g x y
= ((f .) . g) x y = (f .) (g x) y
= (f . g x) y = f ( g x y )
因为 (.) f g x = (f .) g x = (f . g) x = f (g x)
(还有 = (. g) f x
)。
(f .)
称为 运算符部分 (使用 (.)
运算符)。这是写 (.) f
.
的便捷快捷方式
答案是:(a -> b) -> (c -> d -> a) -> c -> d -> b
但是我不知道怎么去。
(.)
具有类型 (b -> c) -> ((a -> b) -> (a -> c))
。为了清楚起见,我特意添加了一些括号。在表达式 (.) . (.)
中有三个 (.)
的实例,因此使用不同字母的三个版本的类型会很方便。
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
–(.)
的第一个实例:(.)
.
(.)
(.) :: (e -> f) -> ((d -> e) -> (d -> f))
–(.)
的第二个实例:(.)
. (.)
(.) :: (h -> i) -> ((g -> h) -> (g -> i))
–(.)
的第三个实例:(.) .
(.)
(.) . (.)
等价于 ((.) (.)) (.)
,它将 (.)
应用到 (.)
,然后将第一个应用的结果应用到 (.)
。
申请一审到二审
将参数类型 ((e -> f) -> ((d -> e) -> (d -> f))
) 与 (.)
(b -> c
) 的输入类型相匹配:
b = (e -> f)
c = ((d -> e) -> (d -> f))
然后将 (.)
((a -> b) -> (a -> c)
) 的结果类型中的类型变量替换为来自参数的匹配项:
(.) (.) :: (a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f)))
将第一次申请的结果应用于第三次
将参数类型 ((h -> i) -> ((g -> h) -> (g -> i))
) 与 (.) (.)
(a -> (e -> f)
) 的输入类型相匹配:
a = (h -> i)
e = (g -> h)
f = (g -> i)
然后将 (.) (.)
(a -> ((d -> e) -> (d -> f))
) 的结果类型中的类型变量替换为来自参数的匹配项:
(.) (.) (.) :: (h -> i) -> ((d -> (g -> h)) -> (d -> (g -> i)))
这与您在问题中的类型相同,只是括号更多,字母不同。如果我删除不必要的括号,结果如下:
(.) (.) (.) :: (h -> i) -> (d -> g -> h) -> d -> g -> i
它有什么作用?它接受两个 d
和 g
类型的参数,对它们应用 d -> g -> h
类型的函数,然后对结果应用 h -> i
类型的函数。
类型(.) :: (b->c) -> (a->b) -> (a->c)
表示
g :: a -> b
f :: d -> c
-------------------- d ~ b
f . g :: a -> c
因此
(.) :: (b->c) -> ((a->b) -> (a->c))
(.) :: ( s -> r ) -> (t->s) -> (t->r)
-------------------------------------------------------------
(.) . (.) :: (b->c) -> (t->s) -> (t->r)
~ (b->c) -> (t->a->b) -> t->a->c
这是有道理的,因为
((.) . (.)) f g x y =
= (.) ((.) f) g x y
= ((f .) . g) x y = (f .) (g x) y
= (f . g x) y = f ( g x y )
因为 (.) f g x = (f .) g x = (f . g) x = f (g x)
(还有 = (. g) f x
)。
(f .)
称为 运算符部分 (使用 (.)
运算符)。这是写 (.) f
.