我是Haskell的初学者,我遇到了函数(.)(.)
,我用它:t
来获取GHCi中的类型:
:t (.)(.)
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
Run Code Online (Sandbox Code Playgroud)
如何理解(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
这里的类型?我很迷茫.
这是组合运算符对组合运算符本身的部分应用。一般来说,我们知道如果我们应用(.)
到某个函数f :: x -> y
,那么
>>> :t (.) f
(.) f :: (a -> x) -> a -> y
Run Code Online (Sandbox Code Playgroud)
因为类型的排列方式:
(b -> c) -> (a -> b) -> a -> c
x -> y
--------------------------------
(a -> x) -> a -> y
Run Code Online (Sandbox Code Playgroud)
我们删除第一个参数,并将剩余出现的b
和替换c
为给定参数的相应类型。
这里,f
又是(.)
,意味着我们识别x ~ (b -> c)
和y ~ (a -> b) -> a -> c
。再次排列类型
(a -> x ) -> a -> y
b -> c (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)
由于a
出现在顶部和底部,我们需要为a
底部选择一个新的变量名称;GHC 选择a1
:
(a -> x ) -> a -> y
b -> c (a1 -> b) -> a1 -> c
Run Code Online (Sandbox Code Playgroud)
将两者放在一起会产生您在 GHCi 中看到的类型。
(a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
Run Code Online (Sandbox Code Playgroud)
抛开解剖学笑话不谈,什么是 (.)(.)
?
假设您有一个函数f :: a -> b
,但您想要一个函数g :: a -> c
,也就是说,您想要f
但具有不同的返回类型。您唯一能做的就是找到一个辅助函数h :: b -> c
来为您转换返回值。那么你的函数就是和g
的组合:h
f
g = h . f
Run Code Online (Sandbox Code Playgroud)
但是,您可能有一个更通用的函数h' :: t -> b -> c
,它可以根据某些参数的值以多种方式将 type 的值转换b
为 type 的值。然后你可以根据该参数得到很多不同的s 。c
x :: t
g
g = (h' x) . f
Run Code Online (Sandbox Code Playgroud)
现在,给定h'
、x
、 和f
,我们可以返回我们的g
,所以让我们编写一个函数来执行此操作:给定一个函数和某个值,该函数将返回值f
从 type 的值“提升”b
为 type 的值:c
h'
x
promote h' x f = (h' x) . f
Run Code Online (Sandbox Code Playgroud)
您可以将任何函数机械地转换为无点形式;我不熟悉细节,但使用PointFree.io会产生
promote = ((.) .)
Run Code Online (Sandbox Code Playgroud)
这只是(.) (.)
写成一个部分的部分应用程序,即:
((.) (.)) h' x f == (h' x) . f
Run Code Online (Sandbox Code Playgroud)
所以,我们的“胸部”运算符只是一个广义的预合成运算符。
归档时间: |
|
查看次数: |
655 次 |
最近记录: |