Был достигнут некоторый прогресс в этой проблеме; спасибо Бравиту (Виталию Брагилевскому)!
Возможно, включено в GHC 7.6.1. (Это? ..)
Как заставить его печатать кириллицу сейчас :
Параметр, передаваемый в GHCi, должен быть функцией, которая может печатать кириллицу. На Hackage такой функции не найдено. Итак, нам нужно создать простую обертку, как сейчас:
module UPPrinter where
import System.IO
import Text.PrettyPrint.Leijen
upprint a = (hPutDoc stdout . pretty) a >> putStrLn ""
И запустить ghci
таким образом: ghci -interactive-print=UPPrinter.upprint UPPrinter
Конечно, это можно записать раз и навсегда в .ghci
.
Практическая задача: придумать альтернативный вариант Show
Итак, теперь возникает практическая проблема: что использовать вместо стандартного Show
, который экранирует нужные символы?
Использование чужой работы: другие красивые принтеры
Выше предлагается Text.PrettyPrint.Leijen
, вероятно, потому что известно, что такие символы не экранируются в строках.
Наш собственный Шоу, основанный на Шоу - привлекательный, но не практичный
Как насчет написания нашего Show
, скажем, ShowGhci
, как было предложено в ответе здесь. Это практично? ..
Чтобы сохранить работу по определению экземпляров для альтернативного класса Show
(например, ShowGhci
), можно поддаться искушению использовать существующие экземпляры Show
по умолчанию, только переопределите экземпляр для String
и Char
. Но это не сработает, потому что если вы используете showGhci = show
, то для любых сложных данных, содержащих строки, show
«сложно компилируется», чтобы вызвать старый show
, чтобы показать строку. В этой ситуации требуется возможность передавать разные словари, реализующие один и тот же интерфейс класса, в функции, которые используют этот интерфейс (show
передаст его до значения show
s). Какие-нибудь расширения GHC для этого?
Основываясь на Show
и желании переопределить только экземпляры для Char
и String
не очень практично, если вы хотите, чтобы оно было "универсальным" (широко применимым), как Show
.
Повторный разбор show
Более практичное (и короткое) решение заключается в другом ответе: проанализируйте выходные данные из show
, чтобы обнаружить символы и строки, и переформатируйте их. (Хотя семантически кажется немного уродливым, решение в большинстве случаев короткое и безопасное (если в show
нет кавычек, используемых для других целей; не должно быть в случае стандартных вещей, потому что идея show
состоит в том, чтобы будь более-менее правильным парсером Haskell.)
Семантические типы в ваших программах
И еще одно замечание.
На самом деле, если мы заботимся об отладке в GHCi (а не просто демонстрируем Haskell и хотим получить симпатичный вывод), необходимость показывать не-ASCII буквы должна исходить из некоторого присущего этим символам в вашей программе (в противном случае, для отладки вы можете заменить их латинскими символами или не заботиться о том, чтобы вам показывали коды). Другими словами, есть некоторые MEANING в этих символах или строках с точки зрения проблемной области. (Например, недавно я занимался грамматическим анализом русского языка, и русские слова в качестве части словаря-примера «присутствовали» в моей программе. Его работа имела смысл только с этими конкретными словами. Поэтому мне нужно было прочитайте их при отладке.)
Но посмотрите, если строки имеют некоторое ЗНАЧЕНИЕ, они больше не являются простыми строками; это данные значимого типа. Возможно, программа станет еще лучше и безопаснее, если вы объявите специальный тип для таких значений.
А потом, ура! Вы просто определяете свой экземпляр Show
для этого типа. И вы в порядке с отладкой вашей программы в GHCi.
Как пример, в моей программеДля грамматического анализа я сделал:
newtype Vocable = Vocable2 { ortho :: String } deriving (Eq,Ord)
instance IsString Vocable -- to simplify typing the values (with OverloadedStrings)
where fromString = Vocable2 . fromString
и
newtype Lexeme = Lexeme2 { lemma :: String } deriving (Eq,Ord)
instance IsString Lexeme -- to simplify typing the values (with OverloadedStrings)
where fromString = Lexeme2 . fromString
(дополнительный fromString
здесь, потому что я мог бы переключить внутреннее представление с String
на ByteString
или что-то еще)
Помимо возможности красиво show
, я стал безопаснее, потому что не смог бы смешивать разные типы слов при составлении своего кода.