我正在做一个Haskell类型的练习,这个练习让我难过。提供的表达式为:
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
closeDrawer();
} else {
super.onBackPressed();
}
}
f2的类型显然是:
f2 f g h = h.g.f
对于如此短暂的表达,这似乎过于复杂。有人可以解释为什么这种类型有意义吗?
答案 0 :(得分:3)
我发现这些“确定这种表达的类型”通常有点倒退。类型应始终排在第一位:您希望为某个任务编写解决方案,将问题描述表示为类型签名。 然后你继续并实际编写一个实现。
在这种情况下,您将从问题开始:我有三个函数f
,g
和h
,以及我可以传递给{{1 }}。此外,函数具有成对匹配结果/参数类型。因此签名
f
你现在可以继续以明确的形式实现这一点,即
f2 :: (α -> β) -> (β -> γ) -> (γ -> δ) -> α -> δ
仍然很简短。毕竟,这是一项非常简单的任务!
但是在Haskell中,您可以使用标准合成运算符f2 f g h x = h (g (f x))
使其更短。最终实现非常短暂的事实基本上只是因为.
与f2
完全相同,只是两次。所以这并不比你有一个非常复杂的具有复杂类型签名的任务更令人惊讶,但发现一些包含一个几乎完成任务的函数的库。显然,调用ready-build函数会比任务复杂性提供更短的实现,但复杂性只是推迟到库函数。
答案 1 :(得分:3)
为什么你认为这很复杂?它只是一个函数,它接受三个函数(匹配类型)并返回一个新函数。
为了保持一致性,我已将b1
重命名为b
并更新了其他名称。所以这是一个略微编辑的版本:
f2 :: (a -> b) -> (b -> c) -> (c -> d) -> a -> d
f2
需要f
,其类型为a -> b
。意思是,它是一个函数,某些类型a
的输入(a
可以是任何东西,这里没有限制)和一些类型b
的返回值。f2
需要g
哪个输入的类型必须与f
的输出匹配,因此它是b -> c
。它不能像e -> c
(其中e
与b
不同),或者代码没有意义,因为无法撰写f . g
}。h
与c -> d
类型完全相同。f2
返回的内容)是一个新函数,它接收f
所做的任何事情并返回h
返回的任何内容,因此它是a -> d
。有了这个,我们已经涵盖了整个类型的定义。基本上,这是一个相对较长的定义,但我认为这是一个非常简单的性质。