如何以无点风格编写此函数



如何以无点风格重写以下函数,将参数x从定义中完全删除(其他两个可能保留(:

between min max x = (min < x) && (x < max)

这不是一项任务,只是一个问题。我不知道该怎么办。我可以把它变成lambda函数

between min max = x -> (min < x) && (x < max)

但这不是无点的,因为x仍然存在。请帮忙。

可以使用Reader应用程序:

between min max = x. (min < x) && (x < max)
{ Convert infix comparisons to sections }
= x. ((min <) x) && ((< max) x)
{ Move infix (&&) to applicative style }
= x. (&&) ((min <) x) ((< max) x)
{ Lift to applicative style using the applicative instance of `(->) a` }
= x. (pure (&&) <*> (min <) <*> (< max)) x
{ Eta-reduce }
= pure (&&) <*> (min <) <*> (< max)
{ Optionally simplify for idiomatic style }
= (&&) <$> (min <) <*> (< max)

另一个解决方案(需要导入Control.Applicative(:

between min max = liftA2 (&&) (min <) (max >)

使用Control.Arrow,我们可以获得几乎混淆的代码:

(min <) &&& (< max) >>> uncurry (&&)

这依赖于用于从左到右构图、f &&& g = x -> (f x, g x)和取消卷曲的预定义>>>


pointfree.io还建议使用以下不可读代码:

between = (. flip (<)) . ap . ((&&) .) . (<)

按操作员段转换,

between min max x = (min < x) && (x < max)
= ((&&) . (min <)) x ((< max) x)

现在这个适合S-组合子Sf g x = (f x) (g x)的模式。Haskell中有很多编码方法,但主要有两种是通过Applicative和Arrows:

_S f g x = (f x) (g x)
= (f <*> g) x
= uncurry id . (f &&& g) $ x

第二个给了我们

between a z = uncurry (&&) . ((a <) &&& (< z))

第一个更合适的

between a z = (&&) <$> (a <) <*> (< z)
= liftA2 (&&) (a <) (< z)
= (a <) <^(&&)^> (< z)     -- nice and visual
(<^) = flip (<$>) 
(^>) = (<*>)

但我们也可以摆弄其他组合子,尽管结果不太令人满意,

_S f g x = f x (g x)
= flip f (g x) x
= (flip f . g) x x
= join (flip f <$> g) x
= (flip f =<< g) x 

= (f x . g) x
= (. g) (f x) x
= ((. g) =<< f) x

这很好地说明了在追求无意义的过程中无意义的危险。

还有一种可能性是有意义的(语法上(,那就是

_S f g x = (f x) (g x)
--   = foldr1 ($) . sequence [f,g] $ x  -- not valid Haskell
-- sequence [f,g] x = [f x,g x]

由于类型问题,这通常不是一个有效的Haskell,但在我们的特定情况下,它确实产生了一个更有效的定义,它似乎也很好地遵循了它的内部逻辑,

between a z = -- foldr1 ($) . sequence [(&&).(a <), (< z)] -- not OK
= foldr1 (&&) . sequence [(a <), (< z)]        -- OK
= and . sequence [(a <), (> z)]

因为CCD_ 9和CCD_。

相关内容

  • 没有找到相关文章

最新更新