计算所有有限Blurgs的无限列表

时间:2015-04-04 12:24:21

标签: haskell

假设我们在Haskell中定义了以下数据类型:

data Blurg = Blub
           | Zarg
           | Parg Blurg Blurg

这意味着ZargParg Blub (Parg Zarg Zarg)Parg (Parg Blub Blub) (Parg Blub Blub)等都是Blurgs的例子。

现在一个旧的考试问题如下:

  

定义一个计算所有Blurgs列表的函数。

所以我试过了:

allBlurg' :: [Blurg] -> [Blurg]
allBlurg' sofar = sofar ++ allBlurg' [Parg x y | x <- sofar, y <- sofar]

allBlurg :: [Blurg]
allBlurg = allBlurg' [Blub, Zarg]

起初我认为这是一个解决方案,但后来我意识到并非所有可能的Blurgs都包含在结果列表allBlurg中。有人可以写一个合适的解决方案吗?

顺便说一句,我只是想指出问题所要求的确实是一个功能,因为它没有采取任何论据;它应该被视为一个价值。其次,虽然问题没有明确说明,但我认为应该是每个Blurg只在列表中出现一次的条件。另请注意,问题实际上只应该询问用户zch在评论中提到的有限Blurgs。

2 个答案:

答案 0 :(得分:9)

基本上,我们需要这个清单:

Blub : Zarg : [ Parg x y | {- `x`,`y` from all possible `Blurg` values -} ]

嗯,实际上你可以像在Haskell中那样写出来:

allBlurg :: [Blurg]
allBlurg = Blub : Zarg : [ Pargs x y | x<-allBlurg, y<-allBlurg ]

BTW这是不是一个函数,尽管定义是递归的。在Haskell中,值可以是递归的!

也许以上内容实际上是在任务中所期望的。麻烦的是,它实际上是错误的:所有Blurg值都将被包含!原因是,y<-allBlurg必须通过无限列表。它永远不会结束,因此x将永远留在第一个元素。即,使用该“解决方案”,您实际上只能获得表单列表

   Pargs Blub . Pargs Blub . Pargs Blub . Pargs Blub ... Pargs Blub $ x

,但Pargs x y除了x之外还有Blub。{/ p>

解决此问题需要什么:枚举两个无限列表中的组合。这是Cantor pairing function,Haskell实现可用here

{-# LANGUAGE MonadComprehensions #-}
import Control.Monad.Omega

allBlurg :: [Blurg]
allBlurg = Blub : Zarg : runOmega [ Pargs x y | x <- each allBlurg
                                              , y <- each allBlurg ]
  

GHCI&GT; :set -XMonadComprehensions
  GHCI&GT; :m + Control.Monad.Omega
  GHCI&GT;让allG = B:Z:runOmega [P x y | x&lt; - 每个allG,y&lt; - all allG]
  GHCI&GT;需要100个全G
  [B,Z,P B B,P B Z,P Z B,P B(P B B),P Z Z,P(P B B)B,
  P B(P B Z),P Z(P B B),P(P B B)Z,P(P B Z)B,P B(P Z B),
  P Z(P B Z),P(P B B)(P B B),P(P B Z)Z,P(P Z B)B,
  P B(P B(P B B)),P Z(P Z B),P(P B B)(P B Z),P(P B Z)(P B B),
  P(P Z B)Z,P(P B(P B B))B,P B(P Z Z),P Z(P B(P B B)),
  P(P B B)(P Z B),P(P B Z)(P B Z),P(P Z B)(P B B),
  P(P B(P B B))Z,P(P Z Z)B,P B(P(P B B)B),P Z(P Z Z),
  P(P B B)(P B(P B B)),P(P B Z)(P Z B),P(P Z B)(P B Z),
  P(P B(P B B))(P B B),P(P Z Z)Z,P(P(P B B)B)B,
  P B(P B(P B Z)),P Z(P(P B B)B),P(P B B)(P Z Z),
  P(P B Z)(P B(P B B)),P(P Z B)(P Z B),P(P B(P B B))(P B Z),
  P(P Z Z)(P B B),P(P(P B B)B)Z,P(P B(P B Z))B,
  P B(P Z(P B B)),P Z(P B(P B Z)),P(P B B)(P(P B B)B),
  P(P B Z)(P Z Z),P(P Z B)(P B(P B B)),P(P B(P B B))(P Z B),
  P(P Z Z)(P B Z),P(P(P B B)B)(P B B),P(P B(P B Z))Z,
  P(P Z(P B B))B,P B(P(P B B)Z),P Z(P Z(P B B)),
  P(P B B)(P B(P B Z)),P(P B Z)(P(P B B)B),P(P Z B)(P Z Z),
  P(P B(P B B))(P B(P B B)),P(P Z Z)(P Z B),
  P(P(P B B)B)(P B Z),P(P B(P B Z))(P B B),P(P Z(P B B))Z,
  P(P(P B B)Z)B,P B(P(P B Z)B),P Z(P(P B B)Z),
  P(P B B)(P Z(P B B)),P(P B Z)(P B(P B Z)),
  P(P Z B)(P(P B B)B),P(P B(P B B))(P Z Z),
  P(P Z Z)(P B(P B B)),P(P(P B B)B)(P Z B),
  P(P B(P B Z))(P B Z),P(P Z(P B B))(P B B),P(P(P B B)Z)Z,
  P(P(P B Z)B)B,P B(P B(P Z B)),P Z(P(P B Z)B),
  P(P B B)(P(P B B)Z),P(P B Z)(P Z(P B B)),
  P(P Z B)(P B(P B Z)),P(P B(P B B))(P(P B B)B),
  P(P Z Z)(P Z Z),P(P(P B B)B)(P B(P B B)),
  P(P B(P B Z))(P Z B),P(P Z(P B B))(P B Z),
  P(P(P B B)Z)(P B B),P(P(P B Z)B)Z,P(P B(P Z B))B,
  P B(P Z(P B Z)),P Z(P B(P Z B)),P(P B B)(P(P B Z)B),
  P(P B Z)(P(P B B)Z),P(P Z B)(P Z(P B B)),
  P(P B(P B B))(P B(P B Z)),P(P Z Z)(P(P B B)B)]

现在,实际上这仍然不完整:它实际上只是所有有限深度 Blurgs的列表。正如zch所说,大多数Blurg是不可计算的,没有机会实际枚举所有

答案 1 :(得分:2)

由于@leftaroundabout解释了问题 - 在您的解决方案中x永远不会匹配第一个元素之外的任何内容,因为y具有无限数量的要匹配的元素。

这是解决这个问题的更基本的解决方案:

nextDepth :: [Blurg] -> [Blurg] -> [Blurg]
nextDepth ls ms =
    [Parg x y | x <- ls, y <- ms] ++
    [Parg x y | x <- ms, y <- ls ++ ms]

deeper :: [Blurg] -> [Blurg] -> [Blurg]
deeper ls ms = ms ++ deeper (ls ++ ms) (nextDepth ls ms)

allBlurg :: [Blurg]
allBlurg = deeper [] [Blub, Zarg]

为了避免无限次迭代的问题,我使用具有不同深度的树的列表。

nextDepth获取深度为< n的树列表和深度为== n的树列表,并返回可以从中构造的深度为== n + 1的树。

对于类似的参数,

deeper返回深度为>= n的树(无限的树除外)。