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?

È stato utile?

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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top