2012-11-11 10 views
12

Ho appena iniziato a insegnarmi Haskell. Questo codice dovrebbe fare il primo fattorizzazione:Haskell - definizione di una funzione con guardie all'interno di un 'dove'

divides :: Integer -> Integer -> Bool 
divides small big = (big `mod` small == 0) 

lowestDivisor :: Integer -> Integer 
lowestDivisor n = lowestDivisorHelper 2 n 
    where lowestDivisorHelper m n 
     | (m `divides` n) = m -- these should belong to lowestDivisorHelper 
     | otherwise = lowestDivisorHelper (m+1) n 

primeFactors :: Integer -> [Integer] 
primeFactors 1 = [] 
primeFactors n 
    | n < 1 = error "Must be positive" 
    | otherwise = let m = lowestDivisor n 
        in m:primeFactors (n/m) 

ottengo un errore di analisi sulla linea commentato. Penso che il mio problema potrebbe essere che lowestDivisorHelper ha guardie, ma il compilatore non sa se le guardie appartengono a lowestDivisorHelper o lowestDivisor. Come faccio a evitare questo?

Modifica: devo aggiungere che non volevo definire la funzione di supporto al livello superiore per nascondere i dettagli dell'implementazione. L'importazione del file non dovrebbe portare con sé la funzione di supporto.

+3

"L'importazione del file non dovrebbe portare con sé la funzione di supporto." In questo caso, non esportarlo. –

risposta

16
lowestDivisor :: Integer -> Integer 
lowestDivisor n = lowestDivisorHelper 2 n where 
    lowestDivisorHelper m n 
     | (m `divides` n) = m -- these should belong to lowestDivisorHelper 
     | otherwise = lowestDivisorHelper (m+1) n 

che serve per iniziare una nuova dichiarazione con la funzione di supporto per le guardie siano sufficientemente rientrati al confronto. (. E anche dimenticato un argomento, n) Questo potrebbe anche funzionare:

lowestDivisor :: Integer -> Integer 
lowestDivisor n = lowestDivisorHelper 2 n 
    where 
    lowestDivisorHelper m n 
     | (m `divides` n) = m -- these should belong to lowestDivisorHelper 
     | otherwise = lowestDivisorHelper (m+1) n 

ma questo non lo fa:

lowestDivisor :: Integer -> Integer 
lowestDivisor n = lowestDivisorHelper 2 n 
    where lowestDivisorHelper m n 
     | (m `divides` n) = m -- these should belong to lowestDivisorHelper 
     | otherwise = lowestDivisorHelper (m+1) n 

Il punto chiave è che il | deve essere seguito il diritto rispetto al nome della funzione.

In generale, l'avvio di una nuova linea continua il precedente finché è più a destra. Le guardie devono continuare dal nome della funzione.

+0

Ah, stavo giusto scrivendo un commento sul fatto che il tuo ultimo esempio andava bene. – Vitus