2015-07-31 10 views
7

Bir Char bir numara ekleyemezsiniz; Aşağıdaki 'a' + 1 derlemek için başarısız olur. Ancak, ['a'..'z'], her karakter değerinin artırıldığı bir dizeyi başarılı bir şekilde oluşturur. Char'u artırabilecek özel bir işlev var mı? Ben chr (ord c + 1) yapabileceğiEnumFromTo nasıl çalışır?

biliyorum.

['a'..'z'] veya alttaki enumFromTo işlevi, sonuçta ortaya çıkan String karakterlerini artırıyor?

cevap

5

Evet, succ adlı Enum sınıfından Char ekleyebilen özel bir işlev var. succ maxBound tanımsız, yani succ uygulamadan önce karakterin değerini kontrol etmeye özen: kısmi olduğunu sakının.

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

Ancak succ kullanılmaz: implementation of succ in GHC önerdiğiniz işlevi oldukça yakın olduğu Aslında

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

: Eğer universe paketiyle doğrulayabilir olarak succ gerçekten \c -> chr (ord c + 1) aynıdır

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 

Eğer squ yapabiliyorsanız: ghc içinde enumFromTo uygulanmasında verimlilik sebebiyle öncelikle var olan pislik geçmiş int eftChar esasen succ kullandığını görebilirsiniz, ama bunun bir satır içine versiyonu yerine succ gerçek bir çağrı (burada, boks önlemek ve yeniden boks Char manipüle ediliyor).

+0

Onun succ' ve 'pred' ve nasıl' Enum' türleri üzerinde işlem 'hakkında bilmek istediğiniz düşünüyorum. Bunu ilk sorumundan anlamadım. –