在Haskell中,如何将约束条件附加到一个参数化的新类型上,使它们自动适用于任何使用它的类实例?[重复]

问题描述 投票:1回答:1

假设我有一个参数类型的定义是这样的。

newtype FancyComplex a b = FancyComplex (a, b)

我打算永远不把这个新类型用于除数字参数以外的任何其他参数。 我的意思是,无论我做什么实现,我都知道参数 ab 将永远是一个实例 Num .

我在这个问题中看到,你可以这样做。在新类型定义中可以使用类型约束吗?

{-# LANGUAGE RankNTypes #-}
newtype (Num a, Num b) => FancyComplex a b = FancyComplex (a, b)

然而这还不够,如果我写任何一个类都是这样的,那么我应该可以写一个新类型定义。

class StupidClass x where add :: x -> x -> x

那么我应该可以写

instance StupidClass (FancyComplex a b) where
    add (FancyComplex (a, b)) (FancyComplex (a', b')) = FancyComplex (a+a', b+b')

但是,没有GHC会告诉我说我没有执行。Num 要求.所以我每次都被迫这样做。

instance (Num a, Num b) => StupidClass (FancyComplex a b) where
    add (FancyComplex (a, b)) (FancyComplex (a', b')) = FancyComplex (a+a', b+b')

在newtype定义中写约束的作用就是迫使我每次都要明确地写约束。好吧,这在我忘记的情况下还是很有用的,但当然,我不希望每次都要重写约束。

我怎样才能自动地、隐式地从newtype定义中继承约束条件呢,这可能吗,如果不可能,有什么理由吗?

目前,我的弱工作方法是定义一个类型别名。type FancyComplexReqs a b = (Num a, Num b)

谢谢你

haskell constraints typeclass newtype
1个回答
3
投票

至少在不改变a的含义的情况下,这是不可能实现的。newtype:

newtype (Num a, Num b) => FancyComplex a b = FancyComplex (a, b)

instance StupidClass (FancyComplex a b) where
    add (FancyComplex (a, b)) (FancyComplex (a', b')) = FancyComplex (a+a', b+b')

最后一行: a+a' 需求功能 + 这是一种 Num所以我们必须要有这样的条件。我只能看到这些选项。

  1. 这个... + 函数存储在 FancyComplex 值。这也行得通,但Haskell报告要求这个 newtype 来拥有相同的内存中的对的表示。没有额外指针的空间。

  2. Num a, Num b 约束被隐式地添加到实例定义中,因为我们在实现中需要它。这样做是可行的,但如果是显式的不是更好吗?拥有隐式约束会使实例更难读,因为即使看起来没有约束,也会有一个约束。

现在,有一个可能的替代方案:如果你想要方案 1,并且你对不同的运行时内存表示方式没有意见,那么使用一个 data 来代替。

data FancyComplex a b where
   FancyComplex :: (Num a, Num b) => a -> b -> FancyComplex a b

这样一来,每一个值都会存储自己的指针到 Num 例。这将需要更多的内存,但对于你的应用来说,这也许不是问题。


3
投票

将约束编码到GADT中,像这样。

{-# LANGUAGE GADTs #-}

data FancyComplex a b where
  FancyComplex :: (Num a, Num b) => a -> b -> FancyComplex a b

class StupidClass x where add :: x -> x -> x

instance StupidClass (FancyComplex a b) where
    add (FancyComplex a b) (FancyComplex a' b') = FancyComplex (a+a') (b+b')

你必须切换到 datanewtype 因为约束变成了字典,而字典是有运行时表示的。然而,通过这样做,我们可以摆脱你的元组,这样可以节省多达 data 费用:

© www.soinside.com 2019 - 2024. All rights reserved.