【问题标题】:'pattern matching' on Typeable types可键入类型的“模式匹配”
【发布时间】:2011-05-04 15:29:31
【问题描述】:

假设,例如,我们有如下数据结构:

data Foo = Bool Bool | Int Int | Double Double

现在,有没有更简单的方法来做到这一点:

foo :: Typeable a => a -> Foo
foo x = maybe (error "i dunno") id $
  liftM Bool   (cast x) `mplus`
  liftM Int    (cast x) `mplus`
  liftM Double (cast x)

有人想过为 Typeable 类型的模式匹配制定语法吗?

【问题讨论】:

    标签: haskell syntax types dynamic-typing


    【解决方案1】:

    使用typeOf 和守卫:

    foo x
        | tx == typeOf "str" = "string"
        | tx == typeOf True  = "bool"
        | otherwise          = "i dunno"
      where tx = typeOf x
    

    【讨论】:

    • 我认为这是一个好方法。一个小问题是 typeOf "str" 在 OverloadedStrings 的存在下无法正常工作,这在如今变得越来越普遍。
    • 数字文字也有类似的问题。当您没有数据类型的构造函数/它们不是纯的时,它也不会扩展到情况。你很快就会得到(undefined :: Foo),这很丑陋。因此,我不喜欢这个解决方案。
    • 字体应该有点难看。它提醒我们回到使用真实类型进行编程,不要再搞乱所有这些运行时糊状了。
    【解决方案2】:

    您可以在这里使用视图模式,它们是非常方便的扩展。

    {-# 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"
    

    结果:

    *Main> :l foo_typeable.hs [1 of 1] 编译 Main(foo_typeable.hs,解释) 好的,已加载模块:主要。 *主> foo "123" *** 例外:我不知道 *主> foo 1 *** 例外:我不知道 *Main> foo (1 :: Int) 诠释 1 *Main> foo (1 :: 整数) *** 例外:我不知道 *Main> foo (1 :: Double) 双1.0

    【讨论】:

    • 这是一个非常巧妙的解决方案!
    【解决方案3】:

    此版本不限于BoolIntDouble,但String 出现为[Char]

    foo :: Typeable a => a -> String
    foo = show . typeOf
    

    【讨论】:

    • ... 这是合理的,因为String 只是[Char] 的类型别名。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 2020-08-09
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多