Suppose, for example, we have the following data structure:
data Foo = Bool Bool | Int Int | Double Double
Now, is there an easier way to do this:
foo :: Typeable a => a -> Foo
foo x = maybe (error "i dunno") id $
liftM Bool (cast x) `mplus开发者_C百科`
liftM Int (cast x) `mplus`
liftM Double (cast x)
Has someone thought of making a syntax for pattern matching on Typeable types?
Use typeOf
and guards:
foo x
| tx == typeOf "str" = "string"
| tx == typeOf True = "bool"
| otherwise = "i dunno"
where tx = typeOf x
You can use view patterns here, they are quite handy extension.
{-# LANGUAGE ViewPatterns #-}
import Data.Data
data Foo = Bool Bool | Int Int | Double Double
deriving (Show)
foo :: Typeable a => a -> Foo
foo (cast -> Just x) = Int x
foo (cast -> Just x) = Bool x
foo (cast -> Just x) = Double x
foo _ = error "i dunno"
Results:
*Main> :l foo_typeable.hs [1 of 1] Compiling Main ( foo_typeable.hs, interpreted ) Ok, modules loaded: Main. *Main> foo "123" *** Exception: i dunno *Main> foo 1 *** Exception: i dunno *Main> foo (1 :: Int) Int 1 *Main> foo (1 :: Integer) *** Exception: i dunno *Main> foo (1 :: Double) Double 1.0
This version doesn't limit itself to Bool
, Int
, or Double
, but a String
comes out as [Char]
.
foo :: Typeable a => a -> String
foo = show . typeOf
精彩评论