Domanda

Sono nuovo di Haskell, e la programmazione in generale. Sto cercando di definire una funzione che genera la sequenza di numeri Collatz da n . Ho:

collatz n = (collatz' n) : 1
   where collatz' n = (takeWhile (>1) (collatz'' n))
          where collatz'' n = n : collatz'' (collatz''' n)
                 where collatz''' 1 = 1
                       collatz''' n = if (even n) then (div n 2) else ((3*2)+1)

Quando ho eseguito questo GHCi, ottengo l'errore:

No instance for (Num [t])
  arising from the literal `2' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [t])

Non so che cosa questo significa. Il problema sembra essere aggiungendo "1" alla lista. Questo problema emerge in quanto

collatz' n = (takeWhile (>0) (collatz'' n))

genera una sequenza infinita di "1" s seguendo la corretta sequenza Collatz; tuttavia,

collatz' n = (takeWhile (>1) (collatz'' n))

genera tutti i numeri di Collatz da n ad eccezione di "1". Che cosa sto facendo di sbagliato?

È stato utile?

Soluzione

risposta

di girarci intorno è corretta, ma dal momento che siete nuovi a Haskell, forse questa è una spiegazione più chiara. L'operatore : pre pends un valore a una lista, così facendo somelist : 7 non è valido in quanto che sta cercando di p pend un valore a un elenco. Ecco perché (collatz' n) : 1 non viene compilato, dal momento che il tipo di (collatz' n) è un elenco di numeri.

provare a sostituire la : 1 con ++ [1].

Altri suggerimenti

(:) :: a -> [a] -> [a]
I suoi primi forze linea collatz n = (collatz' n) : 1 1 a diventare [a].
Credo che si voleva qualcosa di simile (collatz' n) ++ [1]
E avete errore in if (even n) then (div n 2) else ((3*2)+1) ci dovrebbe essere ((3*n)+1 o qualcosa di simile altra cosa avete collatz''' 7 = 7

Un altro modo per andare al problema può essere per l'utilizzo di una struttura Data.Sequence invece di una lista. Sequenze consentono di "SNOC" un valore (mettere un valore sul retro di una sequenza), così come le più usuali "contro" (metterlo sul fronte della sequenza).

Un'altra soluzione per voi potrebbe essere quella di utilizzare span per rendere la propria funzione "takeUntil".

Mi spiego:. span p xs ti dà la stessa risposta come (takeWhile p xs, dropWhile p xs) per qualsiasi funzione di p e la lista xs usereste, allo stesso modo che splitAt n xs è lo stesso di (take n xs, drop n xs)

In ogni caso, è possibile utilizzare span per rendere la propria funzione "takeUntil":

takeUntil p xs = taken ++ take 1 dropped where
                 (taken, dropped) = span p xs

Questa è la forma che stavate cercando, quando è stato utilizzato il modulo collatz n = (collatz' n) : 1.

Spero che questo aiuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top