创建递归地包含彼此的抽象数据类型的实例

时间:2011-04-27 21:04:18

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

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

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)

3 个答案:

答案 0 :(得分:7)

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

foo bar let rec

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 ()

答案 1 :(得分:5)

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 :(得分:0)

由于Haskell的懒惰,以下工作正常。

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