【问题标题】:A concise way to factor out multiple typeclasses in Haskell?在 Haskell 中分解多个类型类的简洁方法?
【发布时间】:2018-07-15 20:41:37
【问题描述】:

在我的 Haskell 代码库中,我有许多采用多态参数的函数。这些多态参数都需要满足相同的类型类集(RealFloat a, Floating a, Real a, Show a, Ord a, Typeable a),并且这组类型类需要存在于函数的类型注释中。

现在我一直在为每个函数手动编写类型类注解,但是在我的代码库中重复 30 多次类型类列表会变得很冗长,而且如果我发现我必须更改每个类型注解也很麻烦需要将另一个类型类添加到列表中。我想知道是否有更简洁的方法来分解出常见的类型类列表。

我真的很想定义一个像typeclass NiceFloating a = RealFloat a, Floating a, Real a, Show a, Ord a, Typeable a 这样的“类型类同义词”,所以我可以在我所有的类型注释中写NiceFloating a => a

如果该功能不存在,也许我可以编写一个“主类型类”,要求一个值满足类型类列表中的每个类型类?但我不想写出所有的操作,例如手工制作 Real、Show 和 Ord — 有没有办法解决这个问题?

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:
    {-# LANGUAGE ConstraintKinds #-}
    type NiceFloating a = (RealFloat a, Floating a, Real a, Show a, Ord a, Typeable a)
    

    这定义了想要的NiceFloating :: * -> Constraint

    【讨论】:

    • 不完全是* -> Constraint,因为它只是一个同义词,所以不能作为那种一等的实体。这个问题很好,但如果需要更多结构,请使用成语class (RealFloat a, Floating a, ...) => NiceFloating a; instance (RealFloat a, Floating a, ...) => NiceFloating a,它可以以更高阶的方式使用。
    • 我也会把它升级到一个类。约束同义词也可以减少那里的重复。 type NiceFloating' a = (...); class NiceFloatingC a => NiceFloating a; instance NiceFloatingC a => NiceFloating a。有点难看,但是当您需要传递 NiceFloating 时可以使用。
    • @luqui 是的,不完全是,但 GHCi 中的 :k 假装它是 * -> Constraint
    • 另外,对于-XLiberalTypeSynonyms,这样的typesyn 可以在一些需要适当类的设置中使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多