Haskell 无点等效

Haskell 无点等效,haskell,pointfree,Haskell,Pointfree,我有这个功能, f::Ord a=>[a]->[(a,Int)] f xs=zipWith(\x ys->(x,长度$filter((,)x.length.filter()-monad解决方案还要长,但它看起来更有条理。我不建议这样做,但无点之王是控件。箭头 import Control.Arrow -- A special version of zipWith' more amenable to pointfree style zipWith' :: ((a, b) -> c) -&g

我有这个功能,

f::Ord a=>[a]->[(a,Int)]
f xs=zipWith(\x ys->(x,长度$filter(
我试着用无点的方式写

f = flip (zipWith (\x -> (,) x . length . filter (< x))) =<< inits
f=flip(zipWith(\x->(,)x.length.filter(
f = flip (zipWith (liftM2 (.) (,) ((length .) . filter . flip (<)))) =<< inits

f=flip(zipWith(liftM2(.)(,)((长度)).filter.flip(作为一般规则:如果一个变量在表达式中出现不止一次,那么将其设为自由点可能不是一个好主意。但是,如果您确定了,最不可读的方法是使用
箭头组合符,因为这样可以非常清楚地显示数据流“拆分”的位置。对于
xs
,我将编写

  uncurry (zipWith (...)) . (id &&& inits)
对于
x
,同样的方法产生

  zipWith ( curry $ uncurry(,) . (fst &&& length . uncurry filter . first(>)) )

这甚至比您使用过的和lambdabot建议的
(>)
-monad解决方案还要长,但它看起来更有条理。

我不建议这样做,但无点之王是
控件。箭头

import Control.Arrow

-- A special version of zipWith' more amenable to pointfree style
zipWith' :: ((a, b) -> c) -> ([a], [b]) -> [c]
zipWith' = uncurry . zipWith . curry

f :: Ord a => [a] -> [(a, Int)]
f = zipWith' (fst &&& (length <<< uncurry filter <<< first (>))) <<< id &&& inits
导入控件。箭头
--zipWith的一个特殊版本“更适合无点风格”
zipWith':((a,b)->c)->([a],[b])->[c]
未经烹调的,未经烹调的咖喱
f::Ord a=>[a]->[(a,Int)]
f=zipWith'(fst&&&(长度与已知

 (f .: g) x y = f (g x y)
这是一本半可读的书

zipWith (curry (fst &&& uncurry (length .: (filter . flip (<))) )) <*> inits
--     \(x,ys) -> (x ,           length  ( (filter . flip (<)) x ys) )

zipWith(curry)(fst&&uncurry)(长度:)过滤翻转((x,长度((过滤翻转(无点样式的要点不仅仅是省略值的名称,而是更喜欢函数的名称。当您使用非常小的定义时,这非常容易做到。当然,如果您内联所有内容而不使用好的名称,任何代码都将变得不可读

让我们从原始函数开始,将其拆分为几个较小的定义

f xs = zipWith combine xs (inits xs)
combine x xs = (x, countWhere (< x) xs)
countWhere f xs = length (filter f xs)
f xs=zipWith combine xs(inits xs)
组合x xs=(x,countWhere(
现在,我们可以轻松地以可读的方式使这些定义变得无意义

f = zipWith combine <*> inits
  where combine = compose (,) countLessThan

compose = liftA2 (.)
countLessThan = countWhere . flip (<)
countWhere = length .: filter
(.:) = (.) . (.)
f=zipWith combine inits
其中combine=compose(,)countLessThan
组合=liftA2(.)
countLessThan=countWhere.flip(我的刺:

f :: Ord a => [a] -> [(a, Int)]
f = zip <*> ((zipWith $ (length .) . filter . (>)) <*> inits)
f::Ord a=>[a]->[(a,Int)]
f=zip((zipWith$(length.).filter(>)inits)
这里我替换了
()
,使之具有
(长度)。filter(>)
作为一个具有正确顺序的参数的函数:
a->[a]->Int
。将它传递给
zipWith
,我们得到
[a]->[a]->[Int]


假设我们在输入中有
[a]
,我们可以将其视为
f([[a]]->[Int])
,用于
Applicative((->[a])
,它可以与
inits::f[[a]]->[Int])结合使用
:f([[a]->[Int])->f[[a]->f[Int]>
并行。
zip
已经是正确的类型:
[a]->[Int]->[(a,Int)]
使用

使用
zipWith'=uncurry.zipWith.curry
是否
知名度足以成为任何标准软件包的一部分?@Bergi我不确定。你可以试试Hoogle的类型。也有一个,或者类似的东西。啊,我刚刚发现(巧合的是,Hoogle没有找到
)@Bergi甚至。谢谢,我不知道这个安装-啊,很好。这就完成了遵循数据思路(re:double-
)的过程。这样,就不会弄乱
咖喱
/
未经修改的
@WillNess是的,首先我写了
zip…
,但使用了
(=@WillNess:)太激动了,它看起来多么简洁。这对我来说是一个很好的练习,我不习惯看这样的函数。我个人,我很快就迷失在这片名称森林中。点对点自由,对我来说,就是不必命名不重要的东西。不仅是参数,还有临时函数——主要是临时函数。@WillNess:是的,我猜是y您应该主要为您希望重用的函数命名,但如果它们可用,您也会更多地重用它们,因为您命名了它们,所以这是一种折衷。
f :: Ord a => [a] -> [(a, Int)]
f = zip <*> ((zipWith $ (length .) . filter . (>)) <*> inits)