可以为元组设置一个特殊的Show实例吗?

Tri*_*Gao 2 haskell

我正在使用所谓的标记,这些标记是带有字符串和标记的元组,我希望我可以使用以下格式在屏幕上呈现:[TAG: VALUE]我不能这样做,因为我没有做正确的事情.这是设置:

type Token value tag = ([value], tag)
data Tag = Whitespace | Alpha | Digit | Punctuation | Terminal
instance Show Tag where
    show Alpha = "A"
    show Whitespace = "W"
    show Digit = "D"
    show Punctuation = "P"
    show Terminal = "|"
type TextToken = Token Char Tag    
instance Show TextToken where
    show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"
Run Code Online (Sandbox Code Playgroud)

在编译时崩溃:

Illegal instance declaration for `Show TextToken'
  (All instance types must be of the form (T t1 ... tn)
   where T is not a synonym.
   Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Show TextToken'
Run Code Online (Sandbox Code Playgroud)

然后我尝试用以下代码替换实例:

instance Show ([Char], Tag) where
   show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"
Run Code Online (Sandbox Code Playgroud)

并再次遇到同样的问题:

Illegal instance declaration for `Show ([Char], Tag)'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Show ([Char], Tag)'
Run Code Online (Sandbox Code Playgroud)

有没有办法让它发挥作用?

J. *_*son 10

你会想要使用newtype

newtype Tag a b = Tag (a, b)

instance (Show a, Show b) => Show (Tag a b) where
  show (Tag (a, b)) = "[" ++ show a ++ ": " ++ show b ++ "]"
Run Code Online (Sandbox Code Playgroud)

你一次遇到几个实例解决方案的狡辩.

  1. 没有{-# LANGUAGE TypeSynonymInstances #-}编译指示,您不能type在实例定义中使用同义词......即使它们非常清楚.启用它很好,它不是Haskell 98.

  2. 在实例定义中使用复杂,嵌套或多参数类型时,经常会遇到过度限制的Haskell 98实例定义.在许多情况下这很好,所以启用{-# LANGUAGE FlexibleInstances #-}pragma将允许这些OK机会.

  3. 最后,危险的是,有已经一个Show例如([Char], Tag),多态一个instance Show (a, b)a ~ [Char]b ~ Tag.这意味着你会违反OverlappingInstances警告.

你可以通过告诉GHC允许OverlappingInstances使用另一个pragma 来禁用它,{-# LANGUAGE OverlappingInstances #-}但由于它可能会导致你自己和使用你代码的其他人的非常奇怪的运行时行为,因此非常不鼓励使用它.

通常,如果您尝试将实例声明"特化"为特定类型,则需要一般情况不存在.

newtype Tup a b = Tup (a, b)

instance Show (Tup Int Int) where
  show (Tup tup) = show tup

instance Show (Tup String Int) where
  show (Tup (s, int)) = s ++ ": " ++ show int

>>> show ("foo", 3)
foo: 3
>>> show (2, 3)
(2, 3)
>>> show ("foo", "bar")
No instance for...
Run Code Online (Sandbox Code Playgroud)