Sve*_*mir 4 haskell typeclass overlapping-instances
我想要实现的是,以下class(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
Run Code Online (Sandbox Code Playgroud)
因为,正如我已经发现的那样,虽然匹配实例声明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
Run Code Online (Sandbox Code Playgroud)
问题:是否有可能(除了通过启用重叠实例)使类型类的任何实例自动成为另一个实例?
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
Run Code Online (Sandbox Code Playgroud)
或者确实
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
Run Code Online (Sandbox Code Playgroud)
where SampleSpace是单一的具体类型,而不是类.