RankNTypes和Existentials - 无法找出最后一步

时间:2016-03-21 17:58:16

标签: haskell polymorphism

这是关于这个主题的前两个问题的延续,接近但仍然是我的最后一步。 RankNTypes中的专家和Haskell中的其他高级类型编程,真的需要你的帮助! :)

有一系列功能可以对表示为向量的列数据执行非常通用的map-reduce,这里是最简单的一个,它采用2个向量,按第1个唯一值进行分组并运行各种聚合第二部分的功能:

groupColumnsG1A1 ::
 (Eq k, G.Vector v k, G.Vector v2 r, Hashable k) =>
   v k -> (v1 -> v1 -> v1) -> (r -> v1) -> v2 r -> Map.HashMap k v1
groupColumnsG1A1 xxs f g yys = G.ifoldl' (\ !acc i x -> Map.insertWith f x (g $ yys G.! i) acc) Map.empty xxs 

给定2个样本向量,加框V.Vector Text cregU.Vector Int64 cint我们可以做一堆很酷的多态事物:

\> groupColumnsG1A1 creg (+) id cint
fromList [("EMEA",345),("NA",681),("RoW",988)]
-- ^ group and sum values in cint

\> groupColumnsG1A1 creg (+) (const 1) cint
fromList [("EMEA",7),("NA",7),("RoW",6)]
-- ^ group and count values in cint

> groupColumnsG1A1 creg (++) (:[]) cint
fromList [("EMEA",[252,12,1,12,24,43,1]),("NA",[4,412,234,2,4,23,2]),("RoW",[24,23,43,252,412,234])]
-- ^ group and put all cint values in lists

到目前为止,所有优秀和时髦 - 并且重要的是要注意这组函数适用于我们可以提供的各种矢量 - 矢量文本,U.Vector Double,U.Vector Int等等。现在,如果你从previous question回忆问题是,现在除了这些纯功能好东西之外,我们还必须与用户交互,解析她的查询并动态构建对纯groupColumnsGnAm的调用。在给出一些有用的想法之后,我现在尝试使用一种类型隐藏系统中的所有各种Vector,以便它们可以存储在1个HashMap中,我们可以根据用户的输入从那里获取它们:

data GenericVector where
GenericVector :: (Show a, Eq a, Hashable a, Vector v a, Show (v a)) => v a -> GenericVector

...然后像我们一样构建对纯函数的调用 - 与上面相同,但是传递GenericVectors而不是特定的向量:

groupColumnsG1A1Gen :: forall v1. Show v1 => 
                   GenericVector -> 
                   (v1 -> v1 -> v1) -> 
                   (forall r. (r -> v1)) -> 
                   GenericVector -> IO ()
groupColumnsG1A1Gen (GenericVector x) f g (GenericVector y) = 
    do let res = groupColumnsG1A1 x f g y
       putStrLn $ show res

所有这个函数都是模式匹配,并从GenericVector展开我们的向量并调用相应的纯函数。 现在,问题就出现了。正如您所看到的,此函数的类型签名遵循groupColumnsG1A1关于fg,因此我和#39; d假设它应该表现出所有相同的灵活性,但如果没有一些RankNTypes魔法,它就不起作用。以上是我能得到的,并且该函数适用于计数示例({ {1}}和greg gint隐藏GenericVectorscreg):

cint

但它总和和列表构建示例都失败了,这里是总和的错误:

\> groupColumnsG1A1Gen  greg (+) (const 1) gint
fromList [("EMEA",7),("NA",7),("RoW",6)]

所以,它不喜欢这里的\> groupColumnsG1A1Gen greg (+) id gint Couldn't match type ‘r’ with ‘Integer’ ‘r’ is a rigid type variable bound by a type expected by the context: r -> Integer at <interactive>:266:1 Expected type: r -> Integer Actual type: Integer -> Integer In the third argument of ‘groupColumnsG1A1Gen’, namely ‘id’ In the expression: groupColumnsG1A1Gen greg (+) id gint - 但它在纯函数情况下完全接受它,具有相同的签名id(除了RankN之外,但没有它没有#&# 39;甚至编译)。

这让我希望自己走上正确的道路,但我的RankN流畅度远不及我自己想要的正确资格,所以任何帮助都非常感激 - 该类型应该是什么签名是支持至少相同的3个案例 - (r->v1)(+) id(+) (const 1)也许它不只是RankNTypes,但我需要一些类型或功能依赖这里?

非常感谢!我承诺根据这种高教育经验编写一本教程,以回馈社区......

PS这里是完整图片列表构建案例的错误:

(++) (:[])

0 个答案:

没有答案