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).
fonte
2015-07-31 20:14:47
Penso che volesse sapere su 'succ' e' pred' e su come operano sui tipi 'Enum'. Non l'ho capito dalla sua domanda iniziale. –