2

我怎样才能做到这一点?

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。

4

1 回答 1

1

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

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

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

于 2013-06-29T18:11:26.157 回答