2009-12-15 6 views
7

Je vais sur cette conférence haskell sur count down game, je ne connais pas de haskell mais je suis intrested dans le problème, j'essaie de porter son code à clojure.Haskell à Clojure

c'est la partie que je suis coincé doit être quelque chose que je ne comprends pas 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)

J'ai moi-même divisé donné 1 2 3 4 il recrache,

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

qui me donne,

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

Est-ce qu'un nyone dites-moi ce qui me manque dans le code haskell? Son code complet est disponible here.

+0

La dernière ligne de votre code Haskell manque-t-elle un carré de fermeture support? –

+1

J'ai jeté un coup d'oeil au même problème ici, bien que plus de force brute que la solution élégante de Graham Hutton. Voir http://www.fatvat.co.uk/2009/02/countdown.html –

+0

merci beaucoup jeff, j'essayais la méthode brute force de toute façon. –

Répondre

4

Ceci est suivi de près la mise en œuvre Haskell aussi loin que ma fu Haskell limitée me permet de faire ....

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

ai pas testé cependant. En ce qui concerne votre message d'erreur: Je pense que le problème est que vous n'appelez pas split récursivement dans exprs. Ensuite, vous obtenez 1 où une séquence est attendue ...

Aléatoire autre remarque: count est linéaire dans le temps pour les séquences. Puisque nous avons juste besoin de savoir, si nous avons plus d'un élément, nous pouvons vérifier la valeur de (next s) par rapport à nil.

+0

Quoi qu'il en soit: nous appelons 'count' dans' split' de toute façon. Alors peu importe. – kotarak

4

L'exception résulte du fait que exprs est appelée récursivement et éventuellement invoquée avec une liste d'entiers. Votre code ne gère qu'une liste de listes ou une liste de longueur.

(exprs '(2 3 4)) 

conduit à la branche else de l'instruction if qui étend vers:

(map #(concat (exprs (first %)) (exprs (second %))) '(2 3 4)))) 

qui sort à:

(concat (exprs (first 2)) (exprs (second 2))) 
(concat (exprs (first 3)) (exprs (second 3))) 
(concat (exprs (first 4)) (exprs (second 4))) 

et (première 2) lancers francs:

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