Is there some way to define an Enum in haskell that wraps around?

后端 未结 5 1022
感情败类
感情败类 2020-12-14 08:13

Consider I was designing a Monopoly game:

data Board = GO | A1 | CC1 | A2 | T1 | R1 | B1 | CH1 | B2 | B3 | 
  JAIL | C1 | U1 | C2 | C3 | R2 | D1 | CC2 | D2 |         


        
5条回答
  •  离开以前
    2020-12-14 08:51

    There is a disgusting way to define an efficient wrapping Enum instance without doing much by hand.

    {-# LANGUAGE MagicHash #-}
    
    import GHC.Exts (Int (..), tagToEnum#, dataToTag# )
    
    -- dataToTag# :: a -> Int#
    -- tagToEnum# :: Int# -> a
    

    Now you can write

    data Board = ... deriving (Eq, Ord, Bounded)
    
    instance Enum Board where
      fromEnum a = I# (dataToTag# a)
    
      toEnum x | x < 0 || x > fromEnum (maxBound :: Board) =
        error "Out of range"
      toEnum (I# t) = tagToEnum# t
      succ x | x == maxBound = minBound
             | otherwise == toEnum (fromEnum x + 1)
      pred x ....
    

提交回复
热议问题