【问题标题】:Scraping some boilerplate刮一些样板
【发布时间】:2013-06-30 02:21:43
【问题描述】:

我怎样才能做到这一点?

data SumTerm = 
     St_TotalSum TotalSum
    |St_SumInS SumInS
    |St_SumInT SumInT
    |St_HTerm HTerm

data Monomial  = Monomial {
    mSumTerm :: SumTerm,
    xPower :: Int,
    yPower :: Int,
    coefficient :: Int
    }

newtype Polynomial = Polynomial [ Monomial ]

{- Ok, here I'm lost, VERY lost -}
toMonomial :: (forall {- a which can be in a SumTerm constructor -} ) 
              => a -> SumTerm
toMonomial sum_term = ....

我当然想到了这个解决方案:

class ToSumTerm a where
     toSumTerm :: a -> SumTerm 

instance ToSumTerm TotalSum where
     toSumTerm total_sum = St_TotalSum total_sum
instance ToSumTerm SumInS where
     toSumTerm sum_in_s = St_SumInS sum_in_s
...

toMonomial :: ToSumTerm a => a -> Monomial 
toMonomial x = Monomial ( toSumTerm a ) 0 0 1 

但它不会自动扩展到 SumTerm 的构造函数。有没有一种简单的方法不必手动编写实例,或者甚至更好,如果可能的话,甚至不用 ToSumTerm 类?换句话说,是否有一些语法允许废弃样板实例定义(或达到等效效果)?如果有解决方案,它当然可以暗示任何 GHC 扩展,例如 GADT。

【问题讨论】:

  • 您的代码中是否有需要对SumTerm 进行模式匹配的部分?如果没有,我认为类型类和 ADT 版本最终都应该随着案例数量线性扩展。
  • @missingno 我同意:如果我很幸运,一切都会线性扩展......但只是为了好奇,我想知道是否有更好的方法。顺便问一下,ADT vs(?) 类型类是什么意思?
  • 次要建议是将类型类 ToMonomialtoMonomial :: a -> Monomial 作为其成员。

标签: haskell


【解决方案1】:

你的SumTerm 数据类型在这里什么都不做,因为它只是包装了一层东西。它也可能是SumTerm a,或者根本不存在。由于每个 Mononomial 只包含一个 SumTerm ,它始终只包含一组固定类型中的一个,因此您可以执行以下操作。

data Monomial a  = Monomial {
    mSumTerm :: a,
    xPower :: Int,
    yPower :: Int,
    coefficient :: Int
    }

当然,一旦你有了一个异质单项式列表或类似的东西,事情就会再次变得有趣,但很难说更普遍的“正确”答案是什么,除非我对你最终想要什么有更深入的了解。

【讨论】:

  • 感谢您的回答。我的目的是将几个“单项”的异构实例组合在一个列表中以形成一个多项式。如您所述, SumTerm 数据类型只是隐藏了具体类型。我的问题可以改写为“是否有一些语法允许废弃样板实例定义?”......相应地进行了编辑。
  • @dsign 你使用TotalSum, SumInS, etc on their own ever? The other option is to inline them into the SumTerm` 类型开头...
猜你喜欢
  • 2021-06-14
  • 2023-03-31
  • 1970-01-01
  • 2019-07-09
  • 2011-07-22
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多