haskell - 实例实现的模式匹配

标签 haskell pattern-matching typeclass

我正在尝试实现一种数据类型的 show 方法。

data OptionList a b = EmptyOpt | OptionList { optListHead :: a, optListTail :: b } deriving (Read)

instance (Show a, Show b) => Show (OptionList a b) where
    show (OptionList a EmptyOpt) = "{" ++ (show a) ++"}"
    show (OptionList EmptyOpt b) = "{" ++ (show b) ++"}"
    show (OptionList a b) = "{"++ (show a) ++ ", " ++ (show b) ++"}"
    show EmptyOpt = ""

如果 ab 之一具有由 EmptyOpt 构造的值,我希望 OptionList 不显示逗号。但是编译器显示如下错误:

OptionList.hs:11:28:
    Couldn't match expected type ‘b’
                with actual type ‘OptionList t0 t1’
      ‘b’ is a rigid type variable bound by
          the instance declaration at OptionList.hs:10:10
    Relevant bindings include
      show :: OptionList a b -> String (bound at OptionList.hs:11:9)
    In the pattern: EmptyOpt
    In the pattern: OptionList a EmptyOpt
    In an equation for ‘show’:
        show (OptionList a EmptyOpt) = "{" ++ (show a) ++ "}"

OptionList.hs:12:26:
    Couldn't match expected type ‘a’
                with actual type ‘OptionList t2 t3’
      ‘a’ is a rigid type variable bound by
          the instance declaration at OptionList.hs:10:10
    Relevant bindings include
      show :: OptionList a b -> String (bound at OptionList.hs:11:9)
    In the pattern: EmptyOpt
    In the pattern: OptionList EmptyOpt b
    In an equation for ‘show’:
        show (OptionList EmptyOpt b) = "{" ++ (show b) ++ "}"

更新:OptionList 应该是类似无类型列表的东西。

(+:) :: a -> b -> (OptionList a b)
infixr 5 +:
t1 +: t2 = OptionList t1 t2

因此,像 0 +: "test"+: True 这样的列表将被定义为 OptionList Int (OptionList String (OptionList Bool EmptyOpt)) 并且会是shown as {0, {"test", {True}}}

最佳答案

你的更新的更新。如果你愿意打开一些扩展,你可以让它工作:

{-# LANGUAGE FlexibleInstances #-}

data EmptyOpt = EmptyOpt

data OptionList a b =
  OptionList a b
  deriving (Read)

instance (Show a, Show b) => Show (OptionList a b) where
  show (OptionList a b) = "{ " ++ show a ++ ", " ++ show b ++ " }"

instance {-# OVERLAPPING  #-} (Show a) => Show (OptionList a EmptyOpt) where
  show (OptionList a EmptyOpt) = "{ " ++ show a ++ " }"

(+:) :: a -> b -> (OptionList a b)
infixr 5 +:
t1 +: t2 = OptionList t1 t2

test = 0 +: "test" +: True +: EmptyOpt

但我个人会尝试使用类似的东西

data Option = B Bool | I Int | S String
data OptionsList = Empty | OptionsList Option OptionsList

您的问题是实例头 ((Show a, Show b) => Show (OptionList a b)) 说您正在为 实现 Show OptionList a b 其中 ab 是具有 Show 实例的任何类型,但在您的实现中,您需要 a b 实际上属于 OptionList 类型。

也许你会改变你的类型,让它更像一个普通的列表:

data OptionList a
  = EmptyOpt
  | OptionList { optListHead :: a
              ,  optListTail :: OptionList a}
  deriving (Read)

那么你可以有一个实例:

instance (Show a) => Show (OptionList a) where
  show (OptionList a EmptyOpt) = "{" ++ show a ++"}"
  show (OptionList a b) = "{"++ show a ++ ", " ++ show b ++"}"
  show EmptyOpt = ""

关于haskell - 实例实现的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41770707/

相关文章:

haskell - 将派生(数据)添加到标准类型

Haskell 的类型系统将数值视为函数?

haskell - Frege 等效于 Haskell 的 getLine 并读取

haskell - 这个质数函数实际上是如何工作的?

haskell - 箭式EDSL,用于编写下层代码

F# 模式匹配中的惯用转换?

f# - 在 F# 中匹配元组的不完整模式

haskell - 类型类和重载,有什么联系?

haskell - 平衡AVL树haskell

c - Automake + 库工具 : pattern rule for per-object CFLAGS?