2015-07-31 4 views
7

Non riesco ad aggiungere un numero a Char; il seguente non riuscirà a compilare 'a' + 1. Ma ancora, ['a'..'z'] crea con successo una stringa in cui ogni valore del carattere viene incrementato. C'è una funzione speciale che può incrementare un Char?Come funziona enumFromTo?

So che posso fare chr (ord c + 1).

In che modo la funzione ['a'..'z'] o la funzione sottostante enumFromTo incrementa i caratteri nel String risultante?

risposta

5

Sì, c'è una funzione speciale che può aggiungere a un Char, dalla stessa classe Enum che è enumFromTo, denominata succ. Fai attenzione che è parziale: succ maxBound non è definito, quindi fai attenzione a controllare il valore del personaggio prima di applicare succ. succ è infatti la stessa di \c -> chr (ord c + 1), come è possibile verificare con il pacchetto universe:

> let avoidMaxBound f x = if x == maxBound then Nothing else Just (f x) 
> avoidMaxBound succ == avoidMaxBound (\c -> chr (ord c + 1)) 
True 

Infatti il ​​implementation of succ in GHC è abbastanza vicino alla funzione che avete suggerito:

instance Enum Char where 
    succ (C# c#) 
     | isTrue# (ord# c# /=# 0x10FFFF#) = C# (chr# (ord# c# +# 1#)) 
     | otherwise    = error ("Prelude.Enum.Char.succ: bad argument") 

Tuttavia, succ non viene utilizzato nella realizzazione di enumFromTo in GHC:

instance Enum Char where 
    {-# INLINE enumFromTo #-} 
    enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y) 
{-# RULES 
"eftChar"  [~1] forall x y.  eftChar x y  = build (\c n -> eftCharFB c n x y) 
#-} 

-- We can do better than for Ints because we don't 
-- have hassles about arithmetic overflow at maxBound 
{-# INLINE [0] eftCharFB #-} 
eftCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> a 
eftCharFB c n x0 y = go x0 
       where 
        go x | isTrue# (x ># y) = n 
         | otherwise  = C# (chr# x) `c` go (x +# 1#) 

{-# NOINLINE [1] eftChar #-} 
eftChar :: Int# -> Int# -> String 
eftChar x y | isTrue# (x ># y) = [] 
      | otherwise   = C# (chr# x) : eftChar (x +# 1#) y 

Se è possibile squ int oltre la cattiveria che esiste principalmente per motivi di efficienza, è possibile vedere che utilizza essenzialmente succ, ma una sua versione inline anziché una chiamata effettiva a succ (qui, per evitare il pugilato e il re-boxing di Char manipolato).

+0

Penso che volesse sapere su 'succ' e' pred' e su come operano sui tipi 'Enum'. Non l'ho capito dalla sua domanda iniziale. –