我想要实现的是,以下类(SampleSpace
)的任何实例都应自动为的实例Show
,因为它SampleSpace
包含创建String表示形式所需的整个接口,因此该类的所有可能实例实际上是相同的。
{-# 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)
也与Rational有关:
[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; dr:不要这样做,或者,如果您坚持要使用-XOverlappingInstances
。
Show
该类的目的。Show
用于简单地显示纯数据,实际上是一种Haskell代码,可以再次使用,从而产生原始值。SampleSpace
也许不应该是一门课。似乎基本上是Map a Rational
与它们相关联的类型的类。为什么不将其用作纯data
类型的字段?Show
当某人为具体类型创建另一个实例时,这样的泛型实例(或者实际上是任何单参数类的泛型实例)Show
也会遇到问题–对于,周围有很多实例。那么,编译器应如何决定使用两个实例中的哪一个?实际上,GHC可以做到这一点:如果您打开-XOverlappingInstances
扩展名,它将选择更具体的扩展名(即被instance SampleSpace s => Show (s a)
任何更具体的实例“覆盖”),但实际上这并不像看起来那么琐碎–如果有人定义了另一个这样的通用实例?重要的是要记住:Haskell类型类始终是开放的,即,基本上,编译器必须假定所有类型可以在任何类中使用。只有当特定实例被调用时,它才真正需要证明,但是它永远不能证明某种类型不在某个类中。我要推荐的内容是-由于该Show
实例不仅显示数据,还应将其设置为其他函数。任何一个
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
或确实
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
其中SampleSpace
是单个具体类型,而不是类。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句