Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 创建每个位置都有新元素的列表列表_List_Haskell_Insert - Fatal编程技术网

List 创建每个位置都有新元素的列表列表

List 创建每个位置都有新元素的列表列表,list,haskell,insert,List,Haskell,Insert,我是haskell的新手,我想知道如何在haskell列表的每个位置插入一个值,并返回包含每个位置值的子列表。例如: insert' :: a -> [a] -> [[a]] insert' a [] = [[a]] insert' a list = ?? 要获得类似于: insert' 7 [1,2,3] = [[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]] P>空列表的情况是自然的,让我们来看看插入'yxSS@(x:xs)。我们基本上需要涵

我是haskell的新手,我想知道如何在haskell列表的每个位置插入一个值,并返回包含每个位置值的子列表。例如:

insert' :: a -> [a] -> [[a]]
insert' a [] = [[a]]
insert' a list = ??
要获得类似于:

insert' 7 [1,2,3] = [[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
<> P>空列表的情况是自然的,让我们来看看<代码>插入'yxSS@(x:xs)。我们基本上需要涵盖两种情况:

  • y
    出现在
    x
    前面。然后我们可以使用
    y:xss
  • y
    出现在
    x
    之后的某个位置。因此,我们只需将其插入列表的其余部分,并确保
    x
    map(x:)
    的第一个元素
  • 虽然它肯定更优雅,但这里有一个带有差异列表的解决方案。如果我们在列表的每个位置插入一个元素
    x
    ys=[y1,y2,…,yn]
    ,第一次我们将把它作为头插入,这意味着我们可以构造
    x:ys

    。对于结果列表的第二个元素,我们要构造一个列表
    [y1,x,y2,…,yn]
    。我们可以像这样做
    y1:x:y2s
    。接下来的列表都将具有结构
    y1:…

    问题是:我们如何编写一个递归结构来跟踪我们希望将元素放入头部的事实。我们可以使用一个函数:我们从一个函数
    id
    开始。如果我们现在调用
    id(x:ys)
    ,那么我们当然会生成列表
    (x:ys)

    但是,我们可以基于
    id
    函数,构造一个新函数
    id2=\z->id(y1:z)
    。因此,此函数将把
    y1
    放在列表的头部,然后添加我们称之为
    id2
    的列表作为尾部。接下来我们可以构造
    id3=\z->id2(y2:z)
    。这将把
    y1
    y2
    作为第一个元素,然后是尾部
    z

    因此,我们可以将其转换为以下递归格式:

    insert' :: a -> [a] -> [[a]]
    insert' x = go id
        where go d [] = [d [x]]
              go d ys@(yh:yt) = (d (x : ys)) : go (d . (yh :)) yt
    
    因此,我们将
    insert'
    重定向到
    go
    ,其中初始差异列表只是
    id
    函数。每次我们检查是否已到达给定列表的末尾。如果是这种情况,我们将返回basecase:我们在差异列表上调用
    [x]
    (作为tail),从而构建一个列表,在其中我们将
    x
    作为最后一个元素追加

    如果我们还没有到达最后一个元素,我们将首先发出
    d(x:ys)
    :我们将
    x
    前置到列表中,并将其作为差异列表
    d
    的参数提供<代码>d将在
    y1:y2:yk
    直到插入
    x
    为止。此外,我们在列表的尾部递归调用
    go(d.(yh:))yt
    :因此我们构造了一个新的差异列表,我们在这里插入
    (yh:)
    ,作为列表的尾部。因此,我们产生了一个带有一个参数的新函数:
    yh
    元素后面的尾部

    此函数产生预期的结果:

    *Main> insert' 4 []
    [[4]]
    *Main> insert' 4 [1,2,5]
    [[4,1,2,5],[1,4,2,5],[1,2,4,5],[1,2,5,4]]
    *Main> insert' 7 [1,2,3]
    [[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
    

    你也可以这样做

    import Data.List
    
    spread :: a -> [a] -> [[a]]
    spread x xs = zipWith (++) (inits xs) ((x:) <$> tails xs)
    
    *Main> spread 7 [1,2,3]
    [[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
    *Main> spread 7 []
    [[7]]
    
    spread :: a -> [a] -> [[a]]
    spread x = zipWith (++) <$> inits <*> fmap (x:) . tails
    
    在本例中,我们将
    fmap
    类型为
    [[a]]->[[a]]->[[a]]->[[a]]
    zipWith(++)
    函数应用于
    fmap(x:)。尾部


    它可能会变得更无意义,但通读起来会变得更复杂(至少对我来说是这样)。在我看来,这是最好的。

    @Zeta
    之前
    之后
    与顺序无关,而是与列表中的位置有关,没有预先假设
    a
    一个我修改过的
    Ord
    @Zeta的实例出现,希望表明这一点。我不是以英语为母语的人,如果有任何建议表达这一点,我将不胜感激。在部分(f y xs)中,这样做的目的是使用列表调用函数,而不使用第一个元素,对吗?@john yes。递归是关于找到子问题,模式的。非常感谢!!看到答案是如此简单真是难以置信,我想我需要大量的练习才能掌握这门语言
    spread :: a -> [a] -> [[a]]
    spread x = zipWith (++) <$> inits <*> fmap (x:) . tails