Проблема при попытке определить Show для моего типа Point3D в Haskell - PullRequest
3 голосов
/ 14 января 2011

Я пытаюсь определить Show для моего Point3D типа:

type Point3D = (Integer, Integer, Integer)

instance Show Point3D where
    show (x,y,z) = "<" ++ (show x) ++ "," ++ (show y) ++ "," ++ (show z) ++ ">"

все же я должен что-то упустить в синтаксисе, поскольку я всегда получаю сообщение об ошибке:

Illegal instance declaration for `Show Point3D'

    (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 Point3D'

Что я делаю не так?

Ответы [ 3 ]

8 голосов
/ 14 января 2011
type Point3D = (Integer, Integer, Integer)

Этот код определяет имя: Point3D, которое является просто сокращением (Integer,Integer,Integer). В любом контексте эти два типа выражений эквивалентны. А для последнего уже существует экземпляр show в Prelude.

Если вам действительно нужно другое строковое представление трехмерной точки, у вас есть следующие альтернативы:

  • Определить простую функцию formatPoint :: Point3D -> String
  • Измените ваш тип, чтобы он отличался от стандартного набора из трех целых чисел, например newtype Point3D = P (Integer,Integer,Integer)
  • Включить языковые расширения, указанные в сообщении об ошибке.

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

Решение нового типа изменяет только синтаксис значений, а не их представление в памяти во время выполнения.

6 голосов
/ 14 января 2011

В качестве альтернативы другим предложениям вы можете определить Point3D как запись:

data Point3D = Point3D { x :: Int, y :: Int, z :: Int }

instance Show Point3D where
    show (Point3D x y z) = concat ["<", show x, ",", show y, ",", show z, ">"]

Или вы помещаете трипель в новый тип:

data Point3D = Point3D (Int, Int, Int)

instance Show Point3D where
    show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]

См. http://learnyouahaskell.com/making-our-own-types-and-typeclasses за и против этих версий.

[Изменить]

Я узнал, что лучше написать последнюю версию как

newtype Point3D = Point3D (Int, Int, Int)

instance Show Point3D where
    show (Point3D (x,y,z)) = concat ["<",(show x),",",show y,",",show z,">"]

Ключевое слово newtype было создано именно для такой ситуации. Преимущество перед data заключается в том, что компилятору не нужно «оборачивать» базовый тип, но он может сохранять его как внутреннее представление, которое и быстрее, и «ленивее».

0 голосов
/ 14 января 2011

Haskell отделяет пространство имен значений и функций от пространства имен типов, классов типов и модулей в случае первой буквы имен.Т.е. функции всегда должны начинаться со строчной буквы.При этом названия типов должны начинаться с заглавной буквы.Поэтому для класса типов Show требуется функция show.

Попробуйте:

type Point3D = (Integer, Integer, Integer)

instance Show Point3D where
    show (x,y,z) = show ""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...