简体   繁体   English

用文件夹在haskell中实现插入

[英]Implement insert in haskell with foldr

How to implement insert using foldr in haskell. 如何在Haskell中使用文件夹实现插入。 I tried: 我试过了:

insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = foldr (\x -> \y -> if x<y then x:y else y:x) [e] xs

No dice. 没有骰子。 I have to insert element e in list so that it goes before first element that is larger or equal to it. 我必须在列表中插入元素e,以便它在大于或等于它的第一个元素之前。

Example: 例:

insert'' 2.5 [1,2,3] => [1.0,2.0,2.5,3.0]
insert'' 2.5 [3,2,1] => [2.5,3.0,2.0,1.0]
insert'' 2 [1,2,1]   => [1,2,2,1]

In last example first 2 is inserted one. 在最后一个示例中,前2个插入了一个。

EDIT: Thanks @Lee. 编辑:谢谢@李。

I have this now: 我现在有这个:

insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = insert2 e (reverse xs)
insert2 e = reverse .  snd . foldr (\i (done, l) -> if (done == False) && (vj e i) then (True, e:i:l) else (done, i:l)) (False, [])
    where vj e i = e<=i

But for this is not working: 但这不起作用:

insert'' 2 [1,3,2,3,3] => [1,3,2,2,3,3]
insert'' 2 [1,3,3,4]   => [1,3,2,3,4]
insert'' 2 [4,3,2,1]   => [4,2,3,2,1]

SOLUTION: 解:

insert'' :: Ord a => a -> [a] -> [a]
insert'' x xs = foldr pom poc xs False
  where
    pom y f je
      | je || x > y = y : f je
      | otherwise   = x : y : f True
    poc True = []
    poc _    = [x]

Thanks @Pedro Rodrigues (It just nedded to change x>=y to x>y.) 感谢@Pedro Rodrigues(它只是想将x> = y更改为x> y。)

(How to mark this as answered?) (如何将此标记为已回答?)

You need paramorphism for that: 为此,您需要同

para  :: (a -> [a] -> r -> r) -> r -> [a] -> r
foldr :: (a ->        r -> r) -> r -> [a] -> r

para  c n (x : xs) = c x xs (para c n xs)
foldr c n (x : xs) = c x    (foldr c n xs)
para  _ n []       = n
foldr _ n []       = n

with it, 用它,

insert v xs = para (\x xs r -> if v <= x then (v:x:xs) else (x:r)) [v] xs

We can imitate paramorphisms with foldr over init . tails 我们可以用foldr代替init . tails来模仿同态init . tails init . tails , as can be seen here: Need to partition a list into lists based on breaks in ascending order of elements (Haskell) . init . tails ,如此处所示: 需要根据元素的升序中断将列表分为多个列表(Haskell)

Thus the solution is 因此解决方案是

import Data.List (tails)

insert v xs = foldr g [v] (init $ tails xs)
  where
    g xs@(x:_) r | v <= x    = v : xs
                 | otherwise = x : r

Another way to encode paramorphisms is by a chain of functions, as seen in the answer by Pedro Rodrigues , to arrange for the left-to-right information flow while passing a second copy of the input list itself as an argument (replicating the effect of tails ): 编码同态的另一种方法是通过函数链,如Pedro Rodrigues答案所示 ,安排从左到右的信息流,同时将输入列表本身的第二个副本作为参数传递(复制了tails ):

insert v xs = foldr g (\ _ -> [v]) xs xs
  where
    g x r xs | v > x     = x : r (tail xs)   -- xs =@= (x:_)
             | otherwise = v : xs

-- visual aid to how this works, for a list [a,b,c,d]:
-- g a (g b (g c (g d (\ _ -> [v])))) [a,b,c,d]

Unlike the version in his answer, this does not copy the rest of the list structure after the insertion point (which is possible because of paramorphism's "eating the cake and having it too"). 与他的答案中的版本不同,这不会在插入点之后复制列表结构的其余部分(这可能是由于同形的“吃蛋糕也吃蛋糕”)。

Here's my take at it: 这是我的看法:

insert :: Ord a => a -> [a] -> [a]
insert x xs = foldr aux initial xs False
  where
    aux y f done
      | done || x > y = y : f done
      | otherwise = x : y : f True
    initial True = []
    initial _ = [x]

However IMHO using foldr is not the best fit for this problem, and for me the following solution is easier to understand: 但是,恕我直言,使用文件foldr不是最适合此问题的解决方案,对我来说,以下解决方案更容易理解:

insert :: Int -> [Int] -> [Int]
insert x [] = [x]
insert x z@(y : ys)
  | x <= y = x : z
  | otherwise = y : insert x ys

I suppose fold isn't handy here. 我想折叠在这里不方便。 It always processes all elements of list, but you need to stop then first occurence was found. 它总是处理list的所有元素,但是您需要先停止然后再找到第一次出现的元素。 Of course it is possible, but you probable don't want to use this: 当然可以,但是您可能不想使用:

insert' l a = snd $ foldl (\(done, l') b -> if done then (True, l'++[b]) else if a<b then (False, l'++[b]) else (True, l'++[a,b])) (False, []) l

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM