在 haskell 中显示约束类型

Show Constraint type in haskell

我正在尝试使用 show 函数将 zerone 的值打印到控制台,但我做不到。这是我的代码:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Control.Arrow
import Data.List
import qualified Data.Map as M
import Data.Function

class Eq a => Bits a where
    zer :: a
    one :: a

instance Bits Int where
    zer = 0
    one = 1

instance Bits Bool where
    zer = False
    one = True

instance Bits Char where
    zer = '0'
    one = '1'

我正在尝试使用函数 show 将 zer 或 one 转换为字符串。 所以我试了一下:

k = zer
show k

但我遇到了这个错误

<interactive>:10:1: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘show’
      prevents the constraint ‘(Show a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance (Show k, Show a) => Show (M.Map k a)
          -- Defined in ‘containers-0.5.7.1:Data.Map.Base’
        instance Show Ordering -- Defined in ‘GHC.Show’
        instance Show Integer -- Defined in ‘GHC.Show’
        ...plus 24 others
        ...plus 11 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: show zer
      In an equation for ‘it’: it = show zer

所以我尝试为展示创建实例。所以我将其添加到我的代码中:

instance (Show a) => Show (Bits a) where
    show zer = "0"
    show one = "1"

但是我又遇到了一个错误

main.hs:25:28: error:
    • Expected a type, but ‘Bits a’ has kind ‘Constraint’
    • In the first argument of ‘Show’, namely ‘Bits a’
      In the instance declaration for ‘Show (Bits a)’

你能告诉我我做错了什么吗?

您正在尝试创建 class 的实例 class,而不是创建 type[=43] =] class 的实例。比较:

Show a => Show (Bits a) -- Invalid

Show a => Show (Maybe a) -- Valid

其中 Maybe 是数据类型,而 Bits 是 class 名称。


我不认为可以表达"anything that has a Bits instance has a Show instance",因为它会导致重叠实例:如果你可以定义类似的东西,那么当你使用show :: Int -> String 编译器不知道是使用 Prelude 的 Show Int 实例还是 Int 定义的 show 作为 Bits 的实例。

一个混乱的解决方法可能是强制执行 "the other direction":Bits 的每个实例都必须是 Show 的实例,这将允许您使用 a' s Show 个实例而不是您自己的实例:

class (Show a, Eq a) => Bits a where
    zer :: a
    one :: a

main = print (zer :: Int)

尽管这需要显式类型签名来解决调用站点 zer 类型中的歧义。