【问题标题】:Cannot print own data type in Haskell无法在 Haskell 中打印自己的数据类型
【发布时间】:2018-09-17 15:33:23
【问题描述】:

在花时间仔细检查此代码之前,请阅读下面的粗体文本之后的问题。如果你不能回答这个问题,我不想浪费你的时间。

好的。我在 Haskell 中创建了自己的数据类型。这是

data Dialogue= Choice String [(String, Dialogue)] 
            | Action String Event
  -- deriving (Show)

请注意注释掉的“派生(显示)”,这对我下面的问题很重要。

我有一个名为 dialog 的函数定义为

dialogue:: Game -> Dialogue -> IO Game
dialogue (Game n p ps) (Action s e) = do 
   putStrLn s
   return (e (Game n p ps))
dialogue (Game n p ps) (Choice s xs) = do
  putStrLn s
  let ys = [ fst a | a <- xs ]
  let i = [1..length ys]
  putStrLn (enumerate 1 ys)
  str <- getLine
  if str `elem` exitWords
  then do
     return (Game n p ps)
  else do
     let c = read str::Int
     if c `elem` i 
     then do 
        let ds = [ snd b | b <- xs ]
        let d = ds !! c
        putStrLn $ show d
        return (Game n p ps)
     else do
        error "error"

我的数据类型游戏定义为

data Game = Game Node Party [Party] | Won 
  deriving (Eq,Show)

而Event是一种类型,我自己定义为

type Event = Game -> Game

现在,这就是我的问题所在。当我在 cmd 中加载此文件时,我 包含派生(显示) 在我的数据类型 Dialogue 中,我收到以下错误:

* No instance for (Show Dialogue) arising from a use of `show'
* In the second argument of `($)', namely `(show d)'
  In a stmt of a 'do' block: putStrLn $ (show d)
  In the expression:
    do let ds = ...
       let d = ds !! c
       putStrLn $ (show d)
       return (Game n p ps)
    |
120 |          putStrLn $ (show d)

在我看来,我需要包含派生(显示),以便能够将此数据类型打印到控制台。但是,当我确实包含 派生(显示) 时,我收到此错误:

* No instance for (Show Event)
    arising from the second field of `Action' (type `Event')
    (maybe you haven't applied a function to enough arguments?)
  Possible fix:
    use a standalone 'deriving instance' declaration,
      so you can specify the instance context yourself
* When deriving the instance for (Show Dialogue)
   |
85 |   deriving Show

我花了很长时间试图找出为什么会发生这种情况。但是我在网上找不到任何似乎记录这个特定问题的地方。

任何帮助都是完美的,甚至只是指向适当解释的链接。

**Edit: ** My Event 是类型同义词,因此我无法将 派生 Show 添加到此

非常感谢

【问题讨论】:

  • Event 必须有一个 Show 实例,以便包含它的事物能够自动派生 Show。这可能意味着将deriving Show 添加到您的Event 定义中。
  • 他的Event类型是别名,不能带派生子句。它也是一个函数,所以自动推导不起作用。
  • 您希望如何打印Event?功能一般不能打印。也许您可以定义自己的自定义instance Show Dialogue,而不依赖于Show Event,例如通过将其显示为一些通用字符串“”。

标签: haskell


【解决方案1】:
type Event = Game -> Game
data Dialogue= Choice String [(String, Dialogue)] 
            | Action String Event
  -- deriving (Show)

当编译器尝试为Dialogue 派生Show 时,它必须在Action 变体中生成ShowEvent,但它不能——Event 是一个函数,而函数不是t 获取自动派生的 Show 实例。

您必须手动实现Show EventShow Dialogue。实现Show Dialogue 的一种方法是:

instance Show Dialogue where
    show (Choice s ds) = " "  `intercalate`  ["Choice", show s, show ds]
    show (Action s e) = " "  `intercalate`  ["Action", show s]

【讨论】:

  • 你也可以用unwords代替intercalate
【解决方案2】:

Event 正如您所定义的,它是一个没有明智的方法来显示的函数。您希望如何显示此信息?一种解决方案是import Text.Show.Functions,它有一个实例。

例如:

Prelude Text.Show.Functions> show (+ 1)
"<function>"

另一种解决方案是定义自己的节目实例:

instance Show (a -> b) where
    show _ = "_"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-07
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    相关资源
    最近更新 更多