【问题标题】:Haskell reverse functionHaskell 反向函数
【发布时间】:2013-07-27 02:36:24
【问题描述】:

对 Haskell 非常陌生,正在尝试创建自己的反向函数。在这里写了这个,但它总是返回一个空列表 [] :

reverse' :: [a] -> [a]
reverse' xs = [xs !! k | k <- [((length xs) - 1)..0]]

谁能解释我做错了什么?

谢谢

【问题讨论】:

  • [length xs - 1, length xs - 2..0] 工作吗?
  • 如果您还不习惯递归,在查看其他实现之前,请尝试以另一种方式定义 reverse,通过填写以下内容:reverse [] = ... ; reverse (x:xs) = ... 并将其视为“空的反面”列表是...,而x 与列表xs 的相反是..."
  • 请注意,按索引访问列表通常是有问题的。它们是专门设计的,因此您可以轻松地递归地从头元素逐个元素地解构它们,但是当您在任意位置请求一个元素时,它们的性能会很差。

标签: haskell functional-programming


【解决方案1】:

正如groovy 提到的,Haskell 范围大多是递增的——也就是说,除非你给它一些提示,否则它不知道如何构造递减列表。看看下面的 ghci 会话:

Prelude> [5..0]
[]
Prelude> [5,4..0]
[5,4,3,2,1,0]

所以,你可以这样构造:

foo xs = [(length xs-1), (length xs -2)..0]
rev xs = [xs !! k| k <- foo xs]

像这样在 ghci 中签出:

Prelude> rev [1..5]
[5,4,3,2,1]

查看Unexpected result while reversing a listHow can I write reverse by foldr efficiently in Haskell? 了解有关反转列表的其他想法。

【讨论】:

  • 但不要忘记检查空列表和单例列表
  • 您可以在foo 中使用where 绑定来避免两次计算xs 的长度。
【解决方案2】:

通常,发明一些不变量并为它写下一些保存法则会有所帮助。这里注意

reverse xs     = reverse xs ++ []
reverse (x:xs) = (reverse xs ++ [x]) ++ []
               = reverse xs ++ ([x] ++ [])
               = reverse xs ++ (x:[])
reverse (x:(y:xs)) =
               = reverse (y:xs) ++ (x:[])
               = reverse xs ++ (y:x:[])
......
reverse (x:(y:...:(z:[])...)) =
               = reverse [] ++ (z:...:y:x:[])

所以如果我们定义

reverse xs = rev xs []  where
  rev (x:xs) acc = rev xs (x:acc)
  rev []     acc = acc

我们准备好了。 :) 即,对于调用rev a b,反转的ab 的串联在从a 获取头部元素并将其前置到b 的转换下保留,直到 em> a 是空的,然后它只是 b。这甚至可以在英文描述之后使用higher-order function until 来表达,如

{-# LANGUAGE TupleSections #-}
reverse = snd . until (null.fst) (\(a,b)-> (tail a,head a:b)) . (, []) 

我们现在也可以定义例如revappend 函数,使用完全相同的内部函数,只是稍微调整了我们的调用方式:

revappend xs ys = rev xs ys  where
  rev (x:xs) acc = rev xs (x:acc)
  rev []     acc = acc

【讨论】:

    【解决方案3】:

    这是我用递归创建自己的反向函数的形式。这个函数非常实用,不用定义辅助函数。

    list = [] reverse [x] = list ++ [x] reverse = list ++ [last l] ++ reverse (init l)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      相关资源
      最近更新 更多