【发布时间】:2021-09-16 03:27:56
【问题描述】:
可能的目标是为 Haskell 中新定义的数据类型创建一个新的 Semigroup 类型类实例(对于那些知道 "Get programming with Haskell" book by Will Kurt 的人,我可能会向您介绍第 428 页,即带有练习扩展的顶点项目 5 的结尾)。
有一个新定义的数据类型:
data HINQ m a b = HINQ (m a -> m b) (m a) (m a -> m a)
| HINQ_ (m a -> m b) (m a)
此数据类型指定类SQL查询,其中m定义上下文(Monad或Alternative),(m a -> m b)是目标类似于SQL函数SELECT的函数,即定义了想要在数据库中看到的属性类型,(m a) 是一个“表”,它应用了前一个函数(类似于 SQL 的 table_name),最后(m a -> m a) 过滤掉了一个是寻找(类似于 SQL 的WHERE)。
我的目标是让这个数据类型成为一个半群(最后是一个 Monoid)的实例。值得一提的是,假设a、b 等所有需要的 Semigroup 实例。
instance (Semigroup a, Semigroup (m a), Semigroup b,...) =>
Semigroup (HINQ m a b) where
(<>) (HINQ func1 start1 test1)
(HINQ func2 start2 test2) =
所以它的粗略想法(在背景上看得更清楚)是可以将几个不同的数据库查询组合成一个查询,但我想不出如何合并两个(m a -> m b) 类型的不同功能同时合并两个表 (m a)... 第一个想法是将它们组合成列表,但是类型签名发生变化我还没有找到解决方案。
【问题讨论】:
-
我不太了解上下文 - 特别是
HINQ的两个不同的数据构造函数 - 所以这可能会导致您找到错误的解决方案,但如果m是 Applicative (它将如果你说它是 Monad 或 Alternative)并且a是一个半群,那么m a可以通过liftA2 (<>)自动成为一个半群。 (不知道如何证明这必然是关联的,但我确信它一定会以某种方式脱离应用法则。) -
这种类型当然可以写一个
Semigroup的实例,甚至可以中规中矩。 (事实上,有一个微不足道的问题 - 为 3 元组的每个组件提升现有的Semigroup实例)。但是这个实例不是唯一的,所以Semigroup法律不会在这里指导您。您应该首先为HINQ写出几个示例值,然后确定您希望它们的半群加法结果的样子。 -
@user2407038,我想我明白了,主要问题是为
(m a -> m b)建立 Semigroup 实例,它(出于后台目的)应该采用“数据库”,例如一些数据a的List并提取所需的信息并以List b的形式返回此数据。问题是如果我有两个不同的函数 f1 和 f2 类型为(m a -> m b)和两个类型为m a的数据集(让我们暂时忘记第三个) 然后我想将这些函数和数据集合并到一个对象中,以便将两个查询表示为一个。 -
@RobinZigmond,感谢提升的想法,现在我应该了解如何将此提升与为第一个函数创建 Semigroup 实例保持一致。对于数据承包商,让我们首先认为好像只有第二个,所以没有最后一个函数。
-
暂时忘记泛型类型。对于
[String] -> [String]类型的两个函数,这个操作是什么样的?例如drop 10 <> take 20的结果是什么?reverse <> id或reverse <> reverse呢?就目前而言,您的问题未得到充分说明-<>的许多实现都可以满足半群定律,并且对于上面的示例都做了不同的事情。你真正想要什么行为?