【问题标题】:Repeatedly call a function: Haskell重复调用一个函数:Haskell
【发布时间】:2013-07-06 11:07:17
【问题描述】:

基本上,我想创建一个函数,它接受一个整数列表和另一个列表(这个列表可以是任何类型),并以指定的间隔从“其他列表”中生成另一个列表,其中包含元素整数列表。如果我输入:

ixs [2,3,1] [3,2,1]
[2,1,3]

到目前为止我有:

ix :: Int -> [a] -> a
ix a [] = error "Empty list"
ix 1 (x:xs) = x
ix a (x:xs) = ix (a-1) xs

ixs :: [Int] -> [a] -> [a]
ixs [] _ = [] 
ixs _ [] = []
ixs (x:xs) (y) = ix x y: []

使用这段代码,我只得到一个返回值,如下所示:

ixs [1,2] [2,1]
[2]

如何在(x:xs) 上重复调用ix 函数,以便它返回我想要的所有值?

编辑:我想在不使用任何标准前奏函数的情况下执行此操作。我只想使用递归。

【问题讨论】:

    标签: list haskell recursion


    【解决方案1】:

    这(几乎)是第一个列表相对于第二个列表的索引(“获取值”)的映射

    import Data.List ((!!))
    -- (!!) :: [a] -> Int -> a
    
    ixs :: [Int] -> [b] -> [b]
    ixs ary ixes = map (ary !!) ixes
    

    但是,当您通过 (3 mod 3 = 0) 索引一个 3 元素列表时,您也有回绕,因此我们应该只将 mod 映射到索引上

    ixs ary ixes = map (ary !!) (map (`mod` length ary) ixes)
    

    然后我们可以简化为“无意义的风格”

    ixs ary = map (ary !!) . map (`mod` length ary)
    

    很好地理解为“映射索引以数组长度为模,然后将数组索引映射到结果索引上”。它给出了正确的结果

    > ixs [2,3,1] [3,2,1] 
    [2,1,3]
    

    为了分解 Prelude 函数和 Data.List 函数,我们有

    (!!) :: [b] -> Int -> b
    (x:_)  !! 0  = x
    (_:xs) !! n
     | n > 0     = xs !! (n-1)
     | otherwise = error "List.(!!): negative argument."
    _      !! _  = error "List.(!!): index too large."
    

    和

    map :: (a -> b) -> [a] -> [b]
    map _ []     = []
    map f (x:xs) = f x : map f xs
    

    【讨论】:

      【解决方案2】:

      你可以颠倒参数的顺序

      ix' :: [a] -> Int -> a
      ix' [] a = error "Empty list"
      ix' (x:xs) 1 = x
      ix' (x:xs) a = ix' xs (a-1)
      

      为了更容易将ix 映射到索引列表:

      ixs' :: [a] -> [Int] -> [a]
      ixs' xs is = map (ix' xs) is
      

      像这样:

      > ixs' "Hello Mum" [1,5,6,1,5,6,1,5]
      "Ho Ho Ho"
      

      但使用 flip 交换参数会更好 - ix' 只是 flip ix,所以你可以这样做

      ixs :: [Int] -> [a] -> [a]
      ixs is xs = map (flip ix xs) is
      

      然后你按照你的计划来称呼它:

      > ixs [1,5,6,1,5,6,1,5] "Hello Mum"
      "Ho Ho Ho"
      

      【讨论】:

      • 谢谢!这真的帮助了我。我从没想过在这个功能中使用地图和翻转。再次感谢!
      【解决方案3】:

      大概是这样的

      ixs :: [Int] -> [a] -> [a]
      ixs idx a = map (`ix` a) idx
      

      您要做的是将索引函数映射到列表中的所有值 索引第二个列表的索引。请注意,您的 ix 函数只是 !! 函数,但从 1 而不是 0 开始索引。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        • 1970-01-01
        • 2016-04-22
        • 2020-04-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-06
        相关资源
        最近更新 更多