【问题标题】:Creating instances of Abstract Data Types that recursively contain each other创建相互递归包含的抽象数据类型的实例
【发布时间】:2011-08-14 05:05:05
【问题描述】:

给定两种定义如下的日期类型:

data Foo = Foo Bar String
data Bar = Bar Foo String

我怎样才能使foobar 使得fooFoo bar "foo"barBar foo "bar"

当我们将类型更改为:

data Foo = Foo Bar (MVar String)
data Bar = Bar Foo (MVar String)

【问题讨论】:

    标签: data-structures haskell recursion abstract-data-type


    【解决方案1】:

    Don按要求回答了这个问题,但一个稍微有趣的问题是如何处理

    data Foo = Foo (MVar Bar) String
    data Bar = Bar (MVar Foo) String
    

    现在这两个 MVar 不仅仅是递归的旁观者,他们是同谋。

    这可以通过两种方式完成:

    1.) 要么做你会用 C 之类的命令式语言做的事情:

    mutation = do
       -- setting up an empty mvar
       bar <- newEmptyMVar
       foo <- newMVar (Foo bar "foo")
       -- and then filling it in
       putMVar bar (Bar foo "foo")
       return (foo, bar)
    

    2.) 或使用 DoRec(以前称为 RecursiveDo)和 mfix 并在幕后喜结连理:

    {-# LANGUAGE DoRec #-} 
    
    mutual = do
       rec foo <- newMVar (Foo bar "foo")
           bar <- newMVar (Bar foo "foo")
       return (foo, bar)
    

    这转化为类似于:

    mutual = do
       (foo, bar) <- mfix $ \(foo, bar) -> do
           foo <- newMVar (Foo bar "foo")
           bar <- newMVar (Bar foo "foo")
           return (foo, bar)
      return (foo, bar)
    

    【讨论】:

      【解决方案2】:

      只需使用let 就足够了(Haskell 中的letletrec,并且支持相互递归定义)。相互递归的定义在堆中设置循环,如下所示:

      MVar 初始化并没有真正以任何有意义的方式改变事情。

      import Control.Concurrent
      
      data Foo = Foo Bar (MVar String)
      
      data Bar = Bar Foo (MVar String)
      
      main = do
          a <- newMVar "foo"
          b <- newMVar "bar"
      
          let foo = Foo bar a
              bar = Bar foo b
      
          return ()
      

      【讨论】:

      • 但是MVars 必须在let 语句之外创建?
      • 没错。它们必须首先在 IO monad 中初始化。而且这里不需要相互单子递归。
      【解决方案3】:

      由于 Haskells 的惰性,以下工作正常。

      data Foo = Foo Bar String deriving Show
      data Bar = Bar Foo String deriving Show
      
      test = let
        foo = Foo bar "foo"
        bar = Bar foo "bar"
        in foo
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-12
        • 1970-01-01
        • 2019-04-07
        • 1970-01-01
        相关资源
        最近更新 更多