English 中文(简体)
GADT 或幻影类型,用于打检查功能调用,但保持类型同性
原标题:GADTs or phantom types to type-check function calls but keep homogeneity of type

我想下面的问题可以用算术解决 但还没有找到解决办法

Problem

我有一个从字符串到值(使用 Tries 作为执行)的有限地图, 我从二进制/文本文件( json, xml,...) 中分析 。

type Value = ...
type Attributes = Data.Trie Value 
data Object = Object Attributes

Each map has the same type of values but not the same set of keys. I group maps with the same set of keys together to be able to prevent having to type-switch all the time I have a specialised function that requires certain keys:

data T1
data T2 
...

data Object a where
    T1 :: Attributes -> Object T1
    T2 :: Attributes -> Object T2
    ...

这让我可以写一些东西 比如:

f1 :: Object T1 -> ...

代替

f1 :: Object ->
f1 o | check_if_T1 o = ...

这有两种缺点:

  1. Homogeneous lists of Object now become heterogeneous, i.e. I cannot have a list [Object] anymore.
  2. 我需要写许多锅炉板才能获得/设置属性:

    get :: Object a -> Attributes
    get (T1 a) = a
    get (T2 a) = a
    ...
    

Question

  1. Is there a better way to specialise functions depending on the constructor of an ADT?
  2. How could I regain the ability to have a list [Object]? Is there a specialized version of Dynamic that only allows certain types? I thought about wrapping the Object again, but this would add a lot of boilerplate. For instance,

    数据对象 = TT1 T1 TT2 T2...

我需要的是:

get :: a -> TObject -> Object a

这样我就可以得出:

collect :: a -> [TObject] -> [Object a]

我查看了HList,但我不认为它适合我的问题。特别是,因为[Object]中的种类顺序在编译时并不为人所知。

这听起来像是可以用功能依赖/类型算术来解决的 但我只是还没有找到一个好办法

问题回答
  1. 如果所有构建器都返回单态 < code> Object 类型且没有循环, 您可能想要考虑仅仅使用不同的类型。 而不是

    data T1
    data T2
    
    data Object a where
        T1 :: Attributes -> Object T1
        T2 :: Attributes -> Object T2
    

    考虑考虑

    data T1 = T1 Attributes
    data T2 = T2 Attributes
    
  2. Dynamic 是一种方法,使用上述方法,您可以添加 发送可输入 并完成。 或者,您可以手工完成:

    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]
    

    正如你说的,这涉及一些锅炉板。 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]
    




相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?

热门标签