繁体   English   中英

我是否正在考虑并正确使用Haskell中的单例类型?

[英]Am I thinking about and using singleton types in Haskell correctly?

我想创建几个不兼容但相同的数据类型。 也就是说,我想要一个参数化类型Foo a ,以及诸如的函数

bar :: (Foo a) -> (Foo a) -> (Foo a) 

实际上不关心什么a是。 为了进一步澄清,我希望类型系统阻止我做

x :: Foo Int
y :: Foo Char
bar x y

虽然我同时并不真正关心IntChar (我只关心他们不一样)。

在我的实际代码中,我有一个给定环上的多项式类型。 我实际上并不关心不确定性是什么,只要类型系统阻止我在t中用多项式添加多项式。 到目前为止,我已经通过创建一个类型类Indeterminate ,并将我的多项式类型参数化为...来解决这个问题

data (Ring a, Indeterminate b) => Polynomial a b

对于Ring部分,这种方法感觉非常自然,因为我确实关心给定多项式结束的特定环。 对于Indeterminate部分感觉非常有用,详情如下。

上述方法工作正常,但感觉做作。 特别是这部分:

class Indeterminate a where
    indeterminate :: a

data T = T

instance Indeterminate T where
    indeterminate = T

data S = S

instance Indeterminate S where
    indeterminate = S

(等等或许还有一些不确定的)。 这感觉奇怪和错误。 本质上,我试图要求Indeterminate实例是单身人士(在这个意义上 )。 奇怪的感觉是我可能会错误地攻击这个问题的一个指标。 另一个原因是我最终不得不注释我的Polynomial ab因为实际的类型b通常无法推断(这并不奇怪,但仍然很烦人)。

有什么建议? 我应该继续这样做,还是我错过了什么?

PS:如果我不立即投票或接受答案,请不要觉得被冒犯。 我将无法再回来查看几天。

首先,我不确定这个:

data (Ring a, Indeterminate b) => Polynomial a b

......正在做你期望的事情。 关于data定义的上下文并不是非常有用 - 请参阅此处的讨论 ,原因可能就是为什么,其中大部分都是强制它们强制您添加额外的注释而不实际提供许多其他类型保证。

其次,除了确保类型保持不同之外,你真的关心“不确定”参数吗? 执行此类事情的一种非常标准的方法是所谓的幻像类型 - 实际上,类型构造函数中的参数未在数据构造函数中使用。 您永远不会使用或需要幻像类型的值,因此函数可以像您想要的那样具有多态性,例如:

data Foo a b = Foo b

foo :: Foo a b -> Foo a b
foo (Foo x) = Foo x

bar :: Foo a c -> Foo b c
bar (Foo x) = Foo x

baz :: Foo Int Int -> Foo Char Int -> Foo () Int
baz (Foo x) (Foo y) = Foo $ x + y

显然这确实需要注释,但仅限于您故意添加限制的地方。 否则,推理将对幻像类型参数正常工作。

在我看来,上述方法应该足以满足您在这里所做的事情 - 单例类型的业务主要是通过创建值的类型代理来弥合更复杂的类型级别的东西和常规的价值级别计算之间的差距。 。 例如,这可以用于标记具有指示其基础的类型的向量,或用物理单位标记数值 - 这两种情况下注释具有更多意义而不仅仅是“不确定的称为X”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM