2009-12-15 10 views
7

Sto andando su questa conferenza di haskell su count down game, non conosco alcun haskell ma sono interessato al problema, sto provando a portare il suo codice per il clojure.Haskell to Clojure

questa è la parte mi sono bloccato deve essere qualcosa che non capisco in 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)

ho la mia divisa data 1 2 3 4 sputa fuori,

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

che mi dà,

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

Può un nyone dimmi cosa mi manca dal codice haskell?

Il suo elenco completo di codici è disponibile here.

+0

L'ultima riga del codice Haskell manca un quadrato di chiusura Staffa? –

+1

Ho dato un'occhiata allo stesso problema qui, anche se più forza bruta come l'elegante soluzione di Graham Hutton. Vedi http://www.fatvat.co.uk/2009/02/countdown.html –

+0

grazie mille jeff, stavo provando comunque il metodo della forza bruta. –

risposta

4

Questo segue da vicino l'attuazione Haskell quanto riguarda la mia limitata fu Haskell mi permette di fare ....

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

non ho ancora testato, però.

Come per il messaggio di errore: Penso che il problema sia che non si chiama split ricorsivamente in exprs. Quindi si ottiene 1 se è prevista una sequenza ...

A caso altra nota: count è lineare nel tempo per le sequenze. Poiché abbiamo solo bisogno di sapere, se abbiamo più di un elemento, possiamo controllare il valore di (next s) contro nil.

+0

Comunque: chiamiamo 'count' in' split' comunque. Quindi non importa. – kotarak

4

l'eccezione deriva dal fatto che ESPR viene chiamato in modo ricorsivo ed eventualmente richiamato con un elenco di numeri interi. il tuo codice gestisce solo un elenco di elenchi o un elenco di lunghezza uno.

(exprs '(2 3 4)) 

conduce al ramo altro del if che si espande verso:

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

che esce a:

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

e (prima 2) tiri liberi:

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