如何通过' TypeRep'?指定值的类型?

时间:2017-10-28 17:52:37

标签: haskell dynamic types polymorphism generic-programming

我的目标是编写带有一些多态值的函数,并列出表示具体类型的typereps。它返回具有相同值的新列表,但已经转换为通过typereps指定的具体类型。

我们有这样的值列表:启用["one", "two"]的{​​{1}} 每个的类型分别为-XOverloadedStrings

我们可以通过这种方式获得的类型代码列表:

IsString a => a

有没有办法获得类型为import Data.Typeable (Proxy(..), typeRep) import Data.Text (Text) [typeRep (Proxy :: Proxy String), typeRep (Proxy :: Proxy ByteString)] 的{​​{1}}和"one"类型的String

P.S。为了根据包含不同类型值的列表来防止错误,我们可以将"two"中的每个值换行,如下例所示(伪代码):

ByteString

可以使用Template Haskell完成,但它太难看了。

2 个答案:

答案 0 :(得分:5)

我无法想象你的目的,但代码可能看起来像这样。我正在使用新的Type.Reflection界面,因为我对它比对经典Data.Typeable更熟悉,但这也适用于此。

import Type.Reflection

types :: [SomeTypeRep]
types = [SomeTypeRep (typeRep @String), SomeTypeRep (typeRep @Text)]

strings :: [String]
strings = ["one", "two"]

converted :: [Dynamic]
converted = fromJust $ zipWithM convert types strings

convert :: SomeTypeRep -> String -> Maybe Dynamic
convert (SomeTypeRep rep) s
  | Just HRefl <- eqTypeRep rep (typeRep @String) = Just $ toDynamic s
  | Just HRefl <- eqTypeRep rep (typeRep @Text) = Just $ toDynamic (fromString s)
  | otherwise = Nothing

答案 1 :(得分:3)

拿着我的啤酒。

{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE OverloadedStrings #-}

import Data.ByteString (ByteString)
import Data.String
import Data.Text (Text)

data Forall c where Forall :: (forall a. c a => a) -> Forall c
data Exists c where Exists :: c a => a -> Exists c
data Evidence c where Evidence :: c a => proxy a -> Evidence c

instance c ~ IsString => IsString (Forall c) where
    fromString s = Forall (fromString s)

asProxyType :: proxy a -> a -> a
asProxyType = const id

downcast :: Evidence c -> Forall c -> Exists c
downcast (Evidence proxy) (Forall v) = Exists (asProxyType proxy v)

polymorphicStrings :: c ~ IsString => [Forall c]
polymorphicStrings = ["one", "two"]

types :: c ~ IsString => [Evidence c]
types = [Evidence ([] :: [ByteString]), Evidence ([] :: [Text])]

monomorphicStrings :: c ~ IsString => [Exists c]
monomorphicStrings = zipWith downcast types polymorphicStrings

要连接问题:Exists TypeableDynamic同构。您可能需要将Forall, Exists :: Constraint -> *概括为Forall, Exists :: [Constraint] -> *,以便同时轻松支持IsStringTypeable,这有点类型级别的黑客攻击,但没有太费劲。类型系列可以为您提供Elem :: Constraint -> [Constraint] -> Bool,可用于替换上面的c ~ IsString

相关问题