随机生成动态数据

时间:2018-02-23 17:33:03

标签: haskell generics types

我在haskell中有一个系统,它使用Data.Dynamic和Type.Reflection来执行推理和计算。我希望能够随机生成动态数据。

当类型已知时,生成动态数据很容易。

goo :: SomeTypeRep -> IO (Dynamic)
goo str = case tyConName . someTypeRepTyCon $ str of
            "Int"  -> return . toDyn . randomRIO $ (-20, 100::Int)
            "Bool" -> return . toDyn . randomRIO $ (True, False)
            _      -> error "no chance"      

但在处理元组时,为每种类型设置一个新行是不切实际的。

有没有办法将n动态组合成一个元组?或者是否有另一种动态生成元组的方法?

1 个答案:

答案 0 :(得分:3)

通常在使用Type.Reflection时,您希望将量化保留为"迟到"尽可能。考虑到这一点,以下似乎有效:

{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE GADTs #-}
import Control.Applicative
import Data.Dynamic
import System.Random
import Type.Reflection

goo :: TypeRep a -> IO a
goo tr = case tr of
    App (App comma a) b | Just HRefl <- eqTypeRep (typeRep @(,)) comma
        -> liftA2 (,) (goo a) (goo b)
    _ | Just HRefl <- eqTypeRep (typeRep @Int) tr -> randomRIO (-20, 100)
      | Just HRefl <- eqTypeRep (typeRep @Bool) tr -> randomIO
      | otherwise -> fail "dunno lol"

您可能会反对要使用现有的Dynamic并生成一个新的,匹配的,随机的,并且这不起作用:

gooBad :: Dynamic -> IO Dynamic
gooBad d = case dynTypeRep d of
    SomeTypeRep tr -> toDyn <$> goo tr

这是真的:SomeTypeRep类型对TypeRep种类存在量化,这是不幸的,因为我们知道它是将代表一种类型*。幸运的是,Data.Dynamic在没有dynTypeRep的情况下导出了足够的信息来自行完成:

gooDyn :: Dynamic -> IO Dynamic
gooDyn (Dynamic tr _) = Dynamic tr <$> goo tr