gpt4 book ai didi

haskell - 使类型类实例自动成为另一个实例

转载 作者:行者123 更新时间:2023-12-04 22:59:52 24 4
gpt4 key购买 nike

我想要实现的是以下类( SampleSpace )的任何实例都应该自动成为 Show 的实例, 因为 SampleSpace包含创建 String 表示所需的整个接口(interface),因此该类的所有可能实例实际上都是相同的。

{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)

class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational

instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es

因为,正如我已经发现的那样,在匹配实例声明时,GHC 只查看头部,而不是约束,因此它认为 Show (s a)也是关于理性的:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )

Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es

问题:是否有可能(除了启用重叠实例)使类型类的任何实例也自动成为另一个类型的实例?

最佳答案

tl;博士 : 不要那样做,或者,如果你坚持,使用 -XOverlappingInstances .

  • 这不是 Show上课是为了。 Show用于简单地显示纯数据,以一种实际上是 Haskell 代码的方式,可以再次使用,产生原始值。
  • SampleSpace或许一开始就不应该是一个类。它似乎基本上是具有 Map a Rational 之类的类型的类。与他们相关联。为什么不直接将其用作普通 data 中的字段?类型?
  • 即使我们接受这个设计……如此通用的Show当有人为具体类型创建另一个实例时,实例(或者实际上是任何单参数类的通用实例)会遇到问题——在 Show 的情况下,当然周围已经有很多实例了。那么编译器应该如何决定使用这两个实例中的哪一个呢? GHC 可以做到,事实上:如果你打开 -XOverlappingInstances扩展,它将选择更具体的一个(即 instance SampleSpace s => Show (s a) 被任何更具体的实例“覆盖”),但实际上这并不像看起来那么简单——如果有人定义了另一个这样的通用实例怎么办?重要的记忆:Haskell 类型类始终是开放的,即基本上编译器必须假设所有类型都可能在任何类中。只有当一个特定的实例被调用时,它才会真正需要证明,但它永远不能证明一个类型不在某个类中。

  • 我推荐的是——因为 Show instance 不仅仅是显示数据,它应该是一个不同的功能。任何一个
    showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String

    或者确实
    showDistribution :: (Show a, Ord a) => SampleSpace a -> String

    在哪里 SampleSpace是单个具体类型,而不是类。

    关于haskell - 使类型类实例自动成为另一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29183805/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com