Haskell: Problema risultato la conversione di divisione di tipo integrale
Domanda
Sto imparando Haskell e bloccato cercando di capire il sistema tipo.
Sto cercando di scrivere una funzione che restituisce la lunghezza della serie 'mezzo o tre Plus One' per un ingresso. Ecco il mio tentativo di funzione, utilizzando un approccio ricorsivo (la funzione è valida per gli ingressi integrali solo):
hotpo :: (Integral a) => a->a
hotpo n = hotpoHelper n 1
hotpoHelper:: (Integral a) => a->a->a
hotpoHelper 1 n = n
hotpoHelper num count
| even num = hotpoHelper (truncate (num/2)) (count+1)
| otherwise = hotpoHelper (3*num+1) (count+1)
Ecco l'errore che ottengo quando provo a caricare il file in GHC 6.12.3
test.hs:8:30:
Could not deduce (RealFrac a) from the context (Integral a)
arising from a use of `truncate' at test.hs:8:30-45
Possible fix:
add (RealFrac a) to the context of
the type signature for `hotpoHelper'
In the first argument of `hotpoHelper', namely
`(truncate (num / 2))'
In the expression: hotpoHelper (truncate (num / 2)) (count + 1)
In the definition of `hotpoHelper':
hotpoHelper num count
| even num = hotpoHelper (truncate (num / 2)) (count + 1)
| otherwise = hotpoHelper (3 * num + 1) (count + 1)
opere take (truncate (5/2)) [1,2,3]
, quindi sono in grado di comprendere questo messaggio di errore.
Dove sto andando male?
Soluzione
L'operatore /
in Haskell è utilizzato per floating point divisione. Se davvero voleva usare la divisione punto e truncate
floating, devi usare fromIntegral
su num
primo a convertirlo in un numero in virgola mobile. L'errore che si ottiene sta dicendo che non è possibile utilizzare la divisione frazionaria su un numero intero (5/2 funziona perché il compilatore deduce un tipo in virgola mobile per entrambi i numeri). Tuttavia, si può fare ciò che si vuole molto più facilmente, usando la funzione div
. Questo è in genere utilizzato infisso, circondando il nome della funzione con apici (questo funziona per qualsiasi funzione Haskell):
| even num = hotpoHelper (num `div` 2) (count+1)