假设我们在Haskell中定义了以下数据类型:
data Blurg = Blub
| Zarg
| Parg Blurg Blurg
这意味着Zarg
,Parg 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。
答案 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
的树(无限的树除外)。