Haskell 转 Clojure

8
我正在学习这个Haskell讲座,它涉及倒数游戏,虽然我不懂Haskell,但我对这个问题很感兴趣,我正在尝试将他的代码移植到Clojure。
这是我卡住的部分,可能是我没有理解Haskell中的某些内容。

split                :: [a] -> [([a],[a])]
split []              = [([],[])]
split (x:xs)          = ([],x:xs) : [(x:ls,rs) | (ls,rs)  [([a],[a])]
nesplit               = filter ne . split

ne                   :: ([a],[b]) -> Bool
ne (xs,ys)            = not (null xs || null ys)

exprs                :: [Int] -> [Expr]
exprs []              = []
exprs [n]             = [Val n]
exprs ns              = [e | (ls,rs) 

我有自己的分割方式,给定 1 2 3 4 后它会输出结果。
(((1) (2 3 4)) ((1 2) (3 4)) ((1 2 3) (4)))


(defn split [v]
  (if (= (count v) 1)
    (list (first v))
    (map #(list (take % v) (drop % v)) (range 1 (count v)))))

(defn exprs [v]
  (if (= (count v) 1) 
    v
    (map #(concat (exprs (first %)) (exprs (second %))) v)))

(exprs (split [1 2 3 4]))


这段文本的意思是:

这个错误信息是:java.lang.IllegalArgumentException: 不知道如何从 java.lang.Integer 创建 ISeq。

有人能告诉我在 Haskell 代码中我漏掉了什么吗?

他的完整代码清单可以在这里找到。


你的 Haskell 代码的最后一行是否缺少一个闭合方括号? - Carl Smotricz
1
我看了一下这里的同样问题,虽然比Graham Hutton的优雅解决方案更加暴力。请参见http://www.fatvat.co.uk/2009/02/countdown.html。 - Jeff Foster
非常感谢Jeff,我本来就在尝试暴力破解方法。 - Hamza Yerlikaya
2个回答

4
这紧密地跟随了Haskell实现,就我有限的Haskell技能而言。
(defn split
  [s]
  (map #(split-at % s) (range 1 (count s))))

(defn ne
  [s]
  (every? (complement empty?) s))

(defn nesplit
  [s]
  (filter ne (split s)))

(declare combine)

(defn exprs
  [s]
  (when-let [s (seq s)]
    (if (next s)
      (for [[ls rs] (nesplit s)
            l       (exprs ls)
            r       (exprs rs)
            e       (combine l r)]
        e)
      s)))

我还没有测试过。
至于你的错误信息:我认为问题在于你没有在exprs中递归调用split。这样会得到1,其中需要序列…
另一随机注意事项:count对于序列是线性的。由于我们只需要知道是否有多个元素,因此可以将(next s)的值与nil进行比较。

4

异常是由于递归调用exprs并最终使用整数列表调用它所导致的。您的代码仅处理列表或长度为一的列表。

(exprs '(2 3 4))

导致if语句进入else分支,其扩展结果为:
(map #(concat (exprs (first %)) (exprs (second %))) '(2 3 4))))

这将变成:
(concat (exprs (first 2)) (exprs (second 2))) 
(concat (exprs (first 3)) (exprs (second 3))) 
(concat (exprs (first 4)) (exprs (second 4))) 

而 (first 2) 抛出的异常:

java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接