我知道(.) f g x = f (g x)
。假设f
的类型为Int -> Int
,g
的类型为Int -> Int -> Int
。现在让h
由h x y = f (g x y).
定义以下哪个陈述为真,为什么(为什么不)?
一个。 h = f . g
湾h x = f . (g x)
℃。 h x y = (f . g) x y
据说,只有b。是真的,而其他人都是假的。我想是的。和b。相当于......说两个功能是平等的。只有当我将参数添加到双方的末尾时,两个函数才相等,它仍然是相等的。所以我得到h x = f . g x
。现在(.)
是一个运算符,因此功能应用程序优先于它,所以f . g x = f . (g x)
,即b。
答案 0 :(得分:4)
这看起来像是一个作业,所以我不会给出哪一个是正确的答案。
您认为a
和b
错误相同。如果将f . g
应用于x
,则会获得(来自(.)
的定义)
(f . g) x = f (g x)
但b
为f . (g x)
,不会扩展为f (g x)
。如果您通过使用b
的定义来关注(.)
,您会在其他人的评论中看到这种感觉。
答案 1 :(得分:0)
函数组合的初始定义有点令人困惑,所以我将以不同的方式编写它:
f . g = \a -> f (g a)
这意味着f . g
返回一个函数,该函数首先将参数应用于g
,然后将结果应用于f
。这在类型签名中也很清楚:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
现在对于你的函数h,它有类似h :: a -> a -> a
的类型。请记住,->
是右关联的,因此类型可以写为h :: a -> (a -> a)
。基本上,h :: a -> b
,虽然此类型会导致错误,因为b
和a
是无法解决的。 (.)
只允许将一个参数应用于第一个函数,所以:
-- One could write,
h x y = f (g x y)
-- But One could also write
h x = f . g x
-- Or, more clearly:
h x = (f) . (g x)
这是因为Haskell函数是 curried ,因此我们可以在不对其进行全面评估的情况下将一些参数应用于g
。
如果我们想象如果我们在视觉上应用(.)
会发生什么,然后简化,我们可以看到它是如何工作的:
h x = \a -> f ((g x) a)
h x = \a -> f (g x a)
h x a = f (g x a)
所以是的,b就是答案。这是因为(.)
只允许在移动到下一个函数之前将一个参数应用于第一个函数。
现在,你可以通过简化我的工作来解决其他不正确的解决方案。这不是太难。