看似合法的Eta减少导致问题

Sam*_*aig 6 haskell pointfree

我试图η-减少功能

foldr :: (a -> b -> b) -> b -> BinaryTree a -> b
foldr combiner base tree = foldMap combiner tree base where
  foldMap = ...
Run Code Online (Sandbox Code Playgroud)

foldMap :: (a -> b -> b) -> BinaryTree a -> b -> b
Run Code Online (Sandbox Code Playgroud)

按预期工作.

我减少了η

foldr combiner base tree = foldMap combiner tree base
Run Code Online (Sandbox Code Playgroud)

foldr combiner = flip $ foldMap combiner where
  ...
Run Code Online (Sandbox Code Playgroud)

这按预期工作.看起来我应该能够完全η-reduce以获得无点功能

foldr = flip $ foldMap where
  ...
Run Code Online (Sandbox Code Playgroud)

但是,这会导致编译错误

Couldn't match type ‘a -> b -> b’ with ‘BinaryTree t0’
Expected type: (a -> b -> b) -> b -> BinaryTree a -> b
  Actual type: BinaryTree t0 -> (t0 -> b -> b) -> b -> b
Run Code Online (Sandbox Code Playgroud)

有可能η-减少更远,如果是这样,怎么样?

Igo*_*dov 10

引发错误,因为g b = f $ a b不等同于g = f $ a.

在第一种情况下,您将获得以下评估顺序:

  • 应用功能ab(调用a具有b作为参数)
  • 将函数f应用于结果

在第二种情况:

  • 将功能f应用于a

因此,你刚才flipfoldMap功能,但实际上要flipfoldMap功能传递combiner给它.这导致我们得出结论,你实际上想要的是组合,即.功能:

foldr = flip . foldMap where
  ...
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是完全正确的(+1),但我要补充一点,我认为`翻转.foldMap`的可读性低于原始代码.确实,'翻转.f`不会立即触发"哦,它是'f`,第二和第三个参数被翻转",就像原始代码一样. (7认同)