参数化类型作为类型参数

时间:2012-09-17 13:56:57

标签: haskell

编译时:

data Rec t = Rec { intPt :: t Int, doublePt :: t Double } deriving Show

type Pt2 a = (a,a)
type Pt3 a = (a,a,a)

type Rec2 = Rec Pt2 
type Rec3 = Rec Pt3

main = do
      print $ Rec (1,2) (3.4,5.6)
      print $ Rec (1,2,3) (5.6, 7.8, 9.0)   

我得到了

Unexpected type `t a' where type variable expected
In the declaration of `Rec (t a)'

如何编译和工作?

2 个答案:

答案 0 :(得分:5)

我无法重现您报告的确切错误消息,但我可以看到您的示例有两个问题。

  1. 您正在尝试为Show派生Rec,它是通过类型构造函数进行参数化的。 GHC目前很难完全自动完成,但你可以通过启用一些扩展来使它在实践中发挥作用。

  2. 您正在使用部分应用的类型同义词Pt2Pt3作为Rec的参数,这是不允许的。您可以通过切换到数据类型来解决此问题。

  3. 更详细一点:要解决问题1,您可以说:

    {-# LANGUAGE StandaloneDeriving, FlexibleContexts, UndecidableInstances #-}
    
    data Rec t = Rec { intPt :: t Int, doublePt :: t Double }
    deriving instance (Show (t Int), Show (t Double)) => Show (Rec t)
    

    通过使用独立派生子句,您可以在Show实例上显式指定前置条件。在这种情况下,这些前提条件也需要启用FlexibleContextsUndecidableInstances扩展名。

    要解决问题2,您可以执行以下操作:

    data Pt2 a = Pt2 a a deriving Show
    data Pt3 a = Pt3 a a a deriving Show
    
    type Rec2 = Rec Pt2 
    type Rec3 = Rec Pt3
    

    可以部分应用数据类型,但类型同义词不能。因此,只有Pt2是数据类型时,才允许使用Rec作为Pt2的参数。通过这些修改,您的主要功能类型检查(和工作):

    main = do
      print $ Rec (Pt2 1 2) (Pt2 3.4 5.6)
      print $ Rec (Pt3 1 2 3) (Pt3 5.6 7.8 9.0)   
    

答案 1 :(得分:0)

我不确定您使用的GHC是什么,但此代码中的错误是:

A.hs:6:1:
    Type synonym `Pt2' should have 1 argument, but has been given none
    In the type synonym declaration for `Rec2'

因为类型同义词可能不会被部分应用,这对于您的Rec2的高级参数是必不可少的。

考虑使用例如键入族或显式数据而不是类型同义词。