Haskell 构造函数作为函数的变量

标签 haskell conventions

这个问题在这里已经有了答案:





Can I match a data constructor wildcard in Haskell?

(2 个回答)


1年前关闭。




我有一个类型,其中有几个构造函数包装了另一种类型;让我们使用下面的示例(实际上我有很多构造函数):

data New a = A a | B a
现在我需要一个函数 fun :: (a -> b) -> New a -> b它应用第一个参数 f :: a -> b包裹在 x :: New a 中的值.我可以通过模式匹配来做到这一点:
fun f (A v) = f v
fun f (B v) = f v
这一点都不优雅!看来我应该能够做 fun f (_ v) = f v 之类的事情相反,但 GHC 给了我 Parse error in pattern .
同样,我想要一个函数 con :: New a -> (a -> New a)它返回构造函数。同样,我可以进行模式匹配:
con (A _) = A
con (B _) = B
将这些统一起来的明显模式是 con (x _) = x ,但这会引发另一个 Parse error in pattern: x .
问题 :
  • 有没有更短、更优雅的方式来定义 funcon通过合并案件?
  • 为什么 GHC 反对这些模式?
  • 我想在这里做一些禁忌吗?

  • 备注 : 我接受过正规的数学培训,但我是自学编程的。我对 haskell 也有些陌生--对不起,如果这个问题有一个明显的、微不足道的答案。我已经尝试了很多谷歌搜索,但我没有任何成功。

    最佳答案

    严格来说,GHC 没有不允许这种事情的技术原因,只是它只有在所有构造函数都具有相同类型的参数时才有效——否则你不能对它们应用相同的函数。
    这给了我们一个见解:大多数时候,可区分联合构造函数具有不同类型的参数,例如 data Thing = Text String | Number Int ,即使类型恰好相同,这通常只是巧合,参数实际上有不同的含义,如data Heisenberg = Velocity Vector2D | Position Vector2D ,因此即使技术上可行,对它们应用相同的功能也是没有意义的。
    这就是歧视工会的本意。构造函数应该代表语义上不同种类的事物。
    这就是为什么 GHC 不支持这种语法的原因,即使类型匹配:它超出了预期的用例,并且大多数时候它是无用的,即使它可能在某些非常狭窄的领域中可能有用。

    但是从您对所需用例的描述来看,您似乎在尝试表达一个完全不同的东西:它看起来像 a在这两个 A aB a A 表示相同的东西和 B仅用作“标签”,以表达值的某些属性,这不是值本身所固有的。例如,a可能是气球的大小,而 AB可以代表气球可以有的两种不同颜色。
    如果这确实是您要表达的内容,那么更好的模型是对标签进行编码,而不是试图硬塞 DU 构造函数来表示它们,然后将标签与记录中的值结合起来:

    data NewTag = A | B
    data New a = New { tag :: NewTag, value :: a }
    
    有了这个定义,funcon变得微不足道:
    fun :: (a -> b) -> New a -> b
    fun f n = f $ value n
    
    con :: NewTag -> a -> New a
    con tag value = New { tag = tag, value = value }
    
    或者如果你喜欢这种事情,那就不用点了:
    fun :: (a -> b) -> New a -> b
    fun f = f . value 
    
    con :: NewTag -> a -> New a
    con = New
    

    关于Haskell 构造函数作为函数的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65524588/

    相关文章:

    haskell - Parsec:跳过第一行

    haskell /FFI : how to handle external dll crashes

    haskell - 与 Functor 合作时的令人振奋的策略

    java - C++ 中的设置/获取方法

    Objective-c 约定当给定 nil 参数时该怎么做?

    haskell - 使用 Stack 安装 X11 软件包时出现 "X11 libraries not found"错误

    haskell - 是否可以使用 Template Haskell 获得任何类型的表达式?

    plugins - 如何在结果中使用约定插件配置我的自定义结果类型

    go - 在方法或构造函数级别进行 Nil 处理?

    java - 将枚举转换为集合/列表