Chr*_*nos 5 haskell algebraic-data-types
我假设使用类型算法可以解决以下问题但尚未找到解决方案.
我有一个从字符串到值的有限映射(使用Tries作为实现),我从二进制/文本文件(json,xml,...)解析.
type Value = ...
type Attributes = Data.Trie Value
data Object = Object Attributes
Run Code Online (Sandbox Code Playgroud)
每个映射都具有相同类型的值,但不具有相同的键集.我将具有相同键集的地图组合在一起,以便能够防止必须一直打字 - 我有一个需要某些键的专门功能:
data T1
data T2
...
data Object a where
T1 :: Attributes -> Object T1
T2 :: Attributes -> Object T2
...
Run Code Online (Sandbox Code Playgroud)
这允许我写下这样的东西:
f1 :: Object T1 -> ...
Run Code Online (Sandbox Code Playgroud)
代替
f1 :: Object ->
f1 o | check_if_T1 o = ...
Run Code Online (Sandbox Code Playgroud)
这有效,但有两个缺点:
我需要编写很多样板来获取/设置属性:
get :: Object a -> Attributes
get (T1 a) = a
get (T2 a) = a
...
Run Code Online (Sandbox Code Playgroud)我怎样才能重新获得列表[对象]的能力?是否有专门版的Dynamic只允许某些类型?我想再次包装Object,但这会增加许多样板.例如,
data TObject = TT1 T1 | TT2 T2 ......
我需要的是:
get :: a -> TObject -> Object a
Run Code Online (Sandbox Code Playgroud)
这样我就可以得出:
collect :: a -> [TObject] -> [Object a]
Run Code Online (Sandbox Code Playgroud)
我查看了HList,但我认为它不适合我的问题.特别是,由于[Object]中的类型顺序在编译时是未知的.
听起来像这可以使用函数依赖/类型算法来解决,但我还没有找到一个很好的方法.
如果所有构造函数都返回单态Object类型并且没有递归,您可能需要考虑仅使用单独的类型。代替
data T1
data T2
data Object a where
T1 :: Attributes -> Object T1
T2 :: Attributes -> Object T2
Run Code Online (Sandbox Code Playgroud)
考虑
data T1 = T1 Attributes
data T2 = T2 Attributes
Run Code Online (Sandbox Code Playgroud)Dynamic是一种方法,使用上面的方法您只需添加deriving Typeable即可完成。或者,您也可以手动完成:
data TSomething = It's1 T1 | It's2 T2
getT1s :: [TSomething] -> [T1]
getT2s :: [TSomething] -> [T2]
getT1s xs = [t1 | It's1 t1 <- xs]
getT2s xs = [t2 | It's2 t2 <- xs]
Run Code Online (Sandbox Code Playgroud)
正如你所说,这涉及一些样板文件。该Typeable版本看起来更好一些:
deriving Typeable T1
deriving Typeable T2
-- can specialize at the call-site to
-- getTs :: [Dynamic] -> [T1] or
-- getTs :: [Dynamic] -> [T2]
getTs :: Typeable a => [Dynamic] -> [a]
getTs xs = [x | Just x <- map fromDynamic xs]
Run Code Online (Sandbox Code Playgroud)