【问题标题】:Applying a (possibly unary) function recursively onto itself将(可能是一元的)函数递归地应用于自身
【发布时间】:2016-01-13 19:45:17
【问题描述】:

我正在尝试在 Haskell https://en.m.wikipedia.org/wiki/L-system 中表达一个 L 系统,特别是 Lindenmayer 用于模拟藻类生长的原始 L 系统。

变量:A B
常量:无
公理:A
规则:(A→AB),(B→A)

对我来说,解决这个问题的自然方法是将规则应用于列表中的每个元素,这(对我而言)意味着我可以使用某种类型的字符串替换来模拟解决方案。

示例:

对于“字符”列表 [A, B, A,我们应用规则并得到 [A → AB, B → A, A → AB] = [A, B, A, A, B] (为了使该模型与 Haskell 很好地配合使用,您必须将 AB 视为一个列表 [A, B],我们将把它与上述规则产生的任何其他结果结合起来。

我已经生成了下面包含的代码,其中包含完整的数据构造函数,不必处理 A 或 B 以外的其他字符,

data Letter = A | B deriving (Show, Eq)

type Alphabet = [Letter]

algae :: Alphabet -> Alphabet

algae = concat . map (\c -> if
                | c == A -> A:[B]
                | c == B -> [A])

上面的代码是这样的,用它自己作为参数调用它会产生预期的结果,即。那个

algae $ algae $algae [A] =  [A, B, A, A, B]

重复的应用程序按预期工作。

接下来我想要完成的是让函数递归地应用于自身,但未能表达这一点。我的意思是我希望能够以algae [A] 或只是algae 的形式调用该函数(这需要将类型签名更改为algae :: Alphabet),这会产生一个无限列表,可以通过应用来接收藻类无数次地贴在自己身上。

自从我承认失败后,我查看了http://hackage.haskell.org/package/lindenmayer-0.1.0.0/docs/Lindenmayer-D0L.html,但我无法理解(目前)代码,并且还发现了其他同样令人困惑的实现。

我已尽力尝试使用foldsfix 函数,但未能成功。我还尝试借鉴其他递归定义,例如

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

但是这种方法失败了,因为zipWith 需要一个二元运算符。 没有单子可以解决这个问题吗?如果有,怎么做?

【问题讨论】:

  • 值得注意的是,[a]Monad 实例实际上只是concatMap,一点也不可怕!
  • 我在 Haskell 的 L-Systems 上写了一篇文章:reinh.com/notes/posts/…

标签: haskell grammar l-systems


【解决方案1】:

您可以使用iterate。我还建议对您的 algae 函数稍作修改以使用模式匹配:

data Letter = A | B deriving (Show, Eq)

type Alphabet = [Letter]

algae :: Alphabet -> Alphabet
algae = concatMap f
  where f A = [A, B]
        f B = [A]

infAlgae :: [Alphabet]
infAlgae = iterate algae [A]

main :: IO ()
main = print $ infAlgae !! 3 

【讨论】:

  • 这几乎是我想要完成的,我希望take 4 infAlgae 成为[A,B,A,A,B] 而不是[[A],[A,B],[A,B,A],[A,B,A,A,B]],但我想我可以想办法以某种方式包装它。没关系,我看到你已经使用!! 这样做了。谢谢!
【解决方案2】:

我想你可能也对如何有效地生成一个实际的无限列表感兴趣,fibs 样式:

import Data.List (stripPrefix)

data Letter = A | B deriving (Show, Eq)

type Alphabet = [Letter]

algae :: Alphabet -> Alphabet
algae = concatMap f
  where f A = [A, B]
        f B = [A]

infFromPrefix :: Eq a => ([a] -> [a]) -> [a] -> [a]
infFromPrefix rule prefix = inf where
    inf = prefix ++ case stripPrefix prefix (rule inf) of
        Just suffix -> suffix
        Nothing     -> error "Substitution does not preserve prefix"

infAlgae :: Alphabet
infAlgae = infFromPrefix algae [A]

main :: IO ()
main = print . take 100 $ infAlgae

在 GHCi 中:

*Main> :main
[A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,A]

【讨论】:

  • 我现在意识到我没有仔细阅读这个问题。我也不知道替换保留了前缀。很好的答案。
猜你喜欢
  • 1970-01-01
  • 2019-02-11
  • 2019-12-05
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多