【问题标题】:Implementing a peeking iterator in Haskell在 Haskell 中实现窥视迭代器
【发布时间】:2011-12-11 02:58:10
【问题描述】:

我正在将一些代码移植到 Haskell,广泛使用 一个窥视的迭代器。它本质上包装了一个集合并提供了两个 功能,“下一个”和“窥视”。 “下一个”功能推进 迭代器并返回头元素,而“peek”函数 返回头元素而不推进迭代器。会是什么 将这个概念转化为 Haskell 的优雅方式?我最好的主意 far 基本上是使用 State monad 来跟踪当前 迭代器的位置。有没有更清洁的方法?

(我也在初学者@上发过这个,但没有得到任何答案)

【问题讨论】:

标签: haskell


【解决方案1】:

副作用迭代器的想法与 Haskell 方式是对立的。您当然可以创建一个 monad,但此时您正在使用 Haskell 作为(引用 Simon PJ 的话)世界上最好的命令式语言。

在不了解您尝试移植的代码的情况下,我无法给出非常具体的建议,但以下是我的一般想法:

  • 使用某种折叠来实现您的迭代。

  • 传递给折叠操作的函数应该由其他函数组合。可能是零个或多个“窥视”操作加上一个“下一个”操作的组合。

如果您的折叠需要a -> b -> a 类型的东西,那么您的peeknext 版本可能都具有这种类型,并且您可以这样组合它们:

peek_then_next :: (a -> b -> a) -> (a -> b -> a) -> (a -> b -> a)

peek_then_next peek next = next'
  where next' a b = let a' = peek a b
                    in  next a' b

您会看到peeknext 参数看起来相同b,但peek 将信息累积到a' 中,然后next 操作可以看到。

您可以根据需要编写任意数量的这些,然后将其传递给foldl 或类似的东西。

【讨论】:

    【解决方案2】:

    通常在 Haskell 中,您将计算一个无限列表(通常由递归函数生成),而不是迭代器。您无需“从迭代器中取出元素”,而是简单地向下迭代列表(通常使用递归函数、折叠或映射等),然后查看列表中您认为合适的元素。因为 Haskell 是惰性的,它只计算你需要的值。

    我认为您应该使用采用无限列表的递归函数来实现您的任务。要“窥视”,只需查看列表的第一个元素。 (您可以根据需要“窥视”列表当前“头部”之后的任意数量的元素,只需通过索引列表即可。)要“推进”迭代器,只需使用列表尾部递归调用自己。

    【讨论】:

      【解决方案3】:
      type Iterator a = [a]
      
      peek :: Iterator a -> a
      peek = head
      
      next :: Iterator a -> Iterator a
      next = tail
      

      您所描述的内容听起来像是 Haskell 的常规旧内置单链表。甚至可能是zipper

      【讨论】:

        【解决方案4】:

        你可以在 Haskell 中做你想做的事,但要注意这些是重炮:

        {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies  #-}
        
        class Iterator as a | as -> a where
          peek :: as -> a
          next :: as -> (as, a)
        
        --sample implementation  
        instance Iterator [a] a where
          peek as = head as
          next as = (tail as, head as) 
        
        --sample use
        main = print $ next $ [3,4]
        --([4],3)
        

        当然Iterator 不会改变,它必须返回它的新版本(与随机数生成器非常相似),但我认为这里的“可变”会有点过分。

        也就是说,我认为你真的应该使用更惯用的方式在 Haskell 中做你想做的事。也许你应该看看Reader monad 是如何工作的:http://learnyouahaskell.com/for-a-few-monads-more#reader

        【讨论】:

          猜你喜欢
          • 2022-01-08
          • 1970-01-01
          • 1970-01-01
          • 2016-05-16
          • 1970-01-01
          • 1970-01-01
          • 2020-11-09
          • 1970-01-01
          • 2018-10-06
          相关资源
          最近更新 更多