Невозможно напечатать собственный тип данных в Haskell

avatar
Frederick
7 апреля 2018 в 22:24
1236
2
2

Пожалуйста, прочитайте мою проблему ниже, после выделенного жирным шрифтом, прежде чем тратить время на тщательное изучение этого кода. Я не хочу тратить ваше время, если вы не сможете ответить на этот вопрос.

Хорошо. Я создал свой собственный тип данных в 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"

Мой тип данных game определяется как

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

И Event — это тип, определенный мною как

type Event = Game -> Game

Вот где возникает моя проблема. Когда я загружаю этот файл в cmd, и у меня есть не включенный вывод в моем (Показать)<91503941 тип данных Диалог, я получаю следующую ошибку:

* 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

Я потратил довольно много времени, пытаясь выяснить, почему это может происходить. Но я не могу найти нигде в Интернете, где бы документировалась эта конкретная проблема.

Любая помощь будет идеальной, или даже просто ссылка на соответствующее объяснение.

**Редактировать: ** My Event является синонимом типа, поэтому я не могу добавить производное Show к этому

Большое спасибо

Источник
Ry-
7 апреля 2018 в 22:27
0

Event должен иметь экземпляр Show, чтобы вещи, содержащие его, могли автоматически получить Show. Вероятно, это означает добавление deriving Show к вашему определению Event.

Thomas M. DuBuisson
7 апреля 2018 в 22:29
0

Его тип Event является псевдонимом и не может содержать производное предложение. Это также функция, поэтому автоматическое получение не будет работать.

chi
7 апреля 2018 в 22:33
0

Как вы ожидаете напечатать Event? Функции не могут быть напечатаны вообще. Возможно, вы могли бы определить свой собственный instance Show Dialogue, не полагаясь на Show Event, например. показывая это как некую общую строку "<event>".

Ответы (2)

avatar
Joker_vD
7 апреля 2018 в 22:35
3
type Event = Game -> Game
data Dialogue= Choice String [(String, Dialogue)] 
            | Action String Event
  -- deriving (Show)

Когда компилятор пытается получить Show для Dialogue, он должен Show и Event в варианте Action, но не может — Event функции не являются функцией и t получить автоматически производные Show экземпляров.

Вы должны вручную реализовать либо Show Event, либо Show 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]
4castle
8 апреля 2018 в 03:29
1

Вы также можете использовать unwords вместо intercalate.

avatar
Thomas M. DuBuisson
7 апреля 2018 в 22:28
5

Event как вы определили, это функция, у которой нет разумного метода для отображения. Как бы вы хотели отобразить эту информацию? Одним из решений является import Text.Show.Functions, у которого есть экземпляр.

Например:

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

Другое решение — определить собственный экземпляр шоу:

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