Haskell 参数化类型作为类型参数

Haskell 参数化类型作为类型参数,haskell,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)

在编译此文件时:

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)'

如何编译并工作?

我不确定您使用的是什么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的更高种类的参数来说是必不可少的


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

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

  • 您正在尝试为通过类型构造函数参数化的
    Rec
    派生
    Show
    。这对于GHC来说目前完全自动完成太难了,但是您可以通过启用许多扩展使其在实践中工作

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

  • 更详细一点:要解决问题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
    实例上显式指定前提条件。在这种情况下,这些先决条件要求同时启用
    FlexibleContexts
    undedicatableinstances
    扩展

    要解决问题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
    是数据类型时,才允许使用
    Pt2
    作为
    Rec
    的参数。通过这些修改,您的主要功能类型检查(并工作):


    我对此投了反对票,因为我认为您发布的代码不是产生错误的代码,这是毫无帮助的。
    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)