【问题标题】:Haskell point-free style with no functions in the expression表达式中没有函数的 Haskell 无点样式
【发布时间】:2019-10-17 12:16:58
【问题描述】:

我一直在尝试采用一些简单的函数并将它们转换为无点样式进行练习。 我从这样的事情开始:

zipSorted x y = (zip . sort) y $ sort x --zipSorted(x, y) = zip(sort(y), sort(x))

并最终将其转换为

zipSorted = flip (zip . sort) . sort

(我不确定这是否是最好的方法,但它确实有效)

现在我试图通过完全不依赖zipsort 来进一步减少这个表达式。换句话说,我正在寻找这个函数:(如果我的词汇没有记错的话,我认为它是一个组合子)

P(f, g, x, y) = f(g(y), g(x))

sort 出现两次但只传入一次的事实暗示我应该使用应用函子运算符<*>,但由于某种原因我不知道如何使用。

据我了解,(f <*> g)(x) = f(x, g(x)),所以我尝试以这种形式重写第一个无点表达式:

flip (zip . sort) . sort
(.) (flip $ zip . sort) sort
(flip (.)) sort $ flip (zip . sort)
(flip (.)) sort $ flip $ (zip .) sort

看来sort应该是x(flip (.))应该是fflip . (zip .)应该是g

p = (flip (.)) <*> (flip . (zip .))
p sort [2, 1, 3] [4, 1, 5]

按预期产生[(1, 1), (4, 2), (5, 3)],但现在我不知道如何将zip 拉出来。我试过了

p = (flip (.)) <*> (flip . (.))
p zip sort [2, 1, 3] [4, 1, 5]

但这不起作用。有没有办法将该表达式转换为分解出zip 的组合子?

【问题讨论】:

  • 稍作备份,您正在寻找zipSorted f g = flip (f . g) . g 的无点定义?
  • 我得到了zipSorted 的无点定义为flip (zip . sort) . sort(它的定义中没有list1list2)但现在我试图将其分解所以它的定义中也没有zipsort(即该函数有4 个参数:zipsortlist1list2
  • 是的,这就是我的问题的意思;我将zipsort 抽象为参数fg,以便zipSorted zip sort 评估为您的原始函数。
  • (我想我应该说,你想要foo f g = flip (f . g) . g的免点版本,所以zipSorted == foo zip sort。)

标签: haskell pointfree combinators


【解决方案1】:

让我们从头开始:

zipSort x y = zip (sort y) (sort x)

它以相反的顺序使用它的参数有点奇怪,但我们可以稍后使用flip 解决这个问题。

这里我们有两个参数的“组合”函数的一般模式(这里:zip)被传递两个由另一个函数转换的值。如果我们有相同的基本参数但不同的转换器,这将是一个liftA2 模式:

  c (f x) (g x)
==
  liftA2 c f g x

但这里恰恰相反:我们在两边都有相同的变换函数(这里:sort),但不同的参数(xy)。那是on:

  c (f x) (f y)
==
  (c `on` f) x y

在你的情况下,我们得到:

zip (sort y) (sort x)
(zip `on` sort) y x
flip (zip `on` sort) x y

所以

zipSort = flip (zip `on` sort)  -- or: flip (on zip sort)

我们可以通过识别标准的二参数合一参数函数组合进一步提取zipsort

(\x y -> f (g x y)) == (f .) . g

给予

zipSort = ((flip .) . on) zip sort

但是,请注意,此功能不如有针对性的版本通用。原函数有类型

(Ord a, Ord b) => [a] -> [b] -> [(b, a)]

但是无点版本有类型

(Ord a) => [a] -> [a] -> [(a, a)]

因为统一这两个sorts 会强制它们具有相同的类型。

【讨论】:

  • 这可以进一步简化。参数化意味着我们可以将flip 推入flip (f `on` g),发出flip f `on` g,或者干脆on . flip
【解决方案2】:

我只是向 lambdabot 询问答案,而不是尝试手动解决:

<amalloy> @pl \zip sort x y -> (zip . sort) y $ sort x
<lambdabot> join . (((.) . flip) .) . (.)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 2021-01-15
    相关资源
    最近更新 更多