【问题标题】:Composite type with extractor type functions具有提取器类型函数的复合类型
【发布时间】:2011-12-28 06:41:28
【问题描述】:

假设我想创建一个复杂的数据结构,其中包含多个相互递归的数据类型、多个类型变量以及一些对这些类型进行操作的函数:

data Foo x y z = FooA x | FooB (Bar x y z) | FooC (Foo x y z) | FooD (Baz x y z)
data Bar x y z = BarA y | BarB (Baz x y z) | BarC (Bar x y z) | BarD (Foo x y z)
data Baz x y z = BazA z | BazB (Foo x y z) | BazC (Baz x y z) | BazD (Bar x y z)

f :: Foo x y z -> Bar x y z -> Baz x y z
g :: Bar x y z -> Baz x y z -> Foo x y z

有没有办法可以捆绑x y z 类型,给它们一个单一的名称t,并在我真正需要它们时取出xyz 类型?我不想在我的数据和函数类型声明中增加 x y z,因为添加额外的参数可能会影响很多代码。

data Foo t = FooA (GetX t) | FooB (Bar t) | FooC (Foo t) | FooD (Baz t)
data Bar t = BarA (GetY t) | BarB (Baz t) | BarC (Bar t) | BarD (Foo t)
data Baz t = BazA (GetZ t) | BazB (Foo t) | BazC (Baz t) | BazD (Bar t)

f :: Foo t -> Bar t -> Baz t
g :: Bar t -> Baz t -> Foo t

我不知道如何定义GetXGetYGetZ 类型“函数”以从包中提取组件类型。

【问题讨论】:

    标签: haskell types


    【解决方案1】:

    您可以使用type families 来做到这一点,但这几乎可以肯定是矫枉过正;通常最好设计您的数据类型,以便它们将来不需要任何其他参数。当然,这非常接近于预测未来,但如果有疑问,您可能应该添加一个参数而不是使用具体类型:)

    如果你有一个具体的例子,我可以给出更具体的建议,但通常最好的办法就是继续使用参数,或者想办法抽象出这三种类型之间的关系,以便你只需要一个完全指定其他参数的参数(而不是将其只是相关类型的列表)。

    不过,下面是一个如何使用类型族实现它的示例:

    type family GetX t
    type instance GetX (a,b,c) = a
    
    type family GetY t
    type instance GetY (a,b,c) = b
    
    type family GetZ t
    type instance GetZ (a,b,c) = c
    

    【讨论】:

    • 整洁!有没有办法使用记录语法而不是普通的元组,以便每个类型族只能处理它感兴趣的字段,使其独立于元组的数量?
    • 这些不是元组值,它们是元组 types — 在 (1,2,3) :: (Int,Int,Int) 中,这些类型函数进行模式匹配的是 (Int,Int,Int) 部分。所以,不,没有记录,对不起:)
    • 另一个答案可能是“如果 Haskell 有你可能有的记录类型,但它没有”。另请参阅关于如何改进 Haskell 的记录系统的永无止境的讨论。
    • 嗯……不完全;即使您有 {a = 42, b = "abc"} 的类型为 {a :: Int, b :: String} 的结构类型样式的东西,它也不会为您提供类型级别的记录类型访问器;您需要的是子类型化,以便 {a :: Int} 上的类型函数模式匹配可以在 {a :: Int, b :: String} 上工作,但子类型化完全是一个全新的事物,并且会使类型推断成为问题。
    • 但是,如果新的自动提升类型到种类的东西能够真正提升记录,它就可以工作。不过,我怀疑这是一个非常重要的优先事项......
    【解决方案2】:

    这基本上相当于类型级别的 lambda。

    type t = (\f -> f x y z)
    
    t Foo --> (\f -> f x y z) Foo --> Foo x y z
    

    当然,tFoo 是翻转的。

    无论如何,Haskell 没有真正的类型级 lambda。但您可能想查看此相关问题的答案:Lambda for type expressions in Haskell?

    【讨论】:

      猜你喜欢
      • 2012-01-10
      • 2021-09-13
      • 2020-09-01
      • 1970-01-01
      • 2011-08-23
      • 2012-08-09
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      相关资源
      最近更新 更多