Подтвердить что ты не робот

Как настроить вывод настраиваемого типа с помощью printf?

Я прочитал хороший кусок Expert F # и работаю над созданием реального приложения. Во время отладки я привык передавать команды fsi, подобные этому, чтобы сделать текст разборчивым в окне repl:

fsi.AddPrinter(fun (x : myType) -> myType.ToString())

Я хотел бы расширить это, чтобы работать с форматом printf, поэтому я мог бы напечатать, например.

printf "%A" instanceOfMyType 

и управлять выходом для пользовательского типа. Из книги следует, что это можно сделать (стр. 93, "Общее структурное форматирование может быть расширено для работы с любыми определенными пользователем типами данных, тема, затронутая на веб-сайте F # "), но я не нашел ссылок на то, как это сделать. Кто-нибудь знает, как это возможно?

Edit:

Я должен был включить образец кода, это тип записи, с которым я имею дело, например

type myType = 
    {a: int}        
    override m.ToString() = "hello"

let t = {a=5}
printfn "%A" t
printfn "%A" (box t)  

оба вывода print дают:

{a = 5;}
4b9b3361

Ответ 1

Похоже, что правильный способ сделать это в F # 2.0 - это использовать атрибут StructuredFormatDisplay, например:

[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}

В этом примере вместо стандартного {a = 42;} вы получите hello 42.

Это работает одинаково для типов объектов, записей и соединений. И хотя шаблон должен иметь формат "PreText {PropertyName} PostText" (PreText и PostText необязательны), это на самом деле более мощное, чем ToString(), потому что:

  • PropertyName может быть свойством любого типа. Если это не строка, она также будет подвергнута структурированному форматированию. Блог Don Syme дает пример рекурсивного форматирования дерева таким образом.

  • Это может быть вычисленное свойство. Таким образом, вы действительно можете получить ToString() для работы с типами записей и объединений, хотя и довольно круто:

    [<StructuredFormatDisplay("{AsString}")>]
    type myType = 
        {a: int}
        override m.ToString() = "hello"
        member m.AsString = m.ToString()  // a property that calls a method
    

Кстати, ToString() всегда будет использоваться (даже для типов записей и объединений), если вы вызываете printfn "%O" вместо printfn "%A".

Ответ 2

Хм... Я смутно вспоминаю некоторые изменения в этом, но я забыл, что они произошли до или после CTP (1.9.6.2).

В любом случае, на CTP, я вижу, что

type MyType() =
    override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs

при оценке в окне VFSI делает то, что я хочу, и что

x;;
xs;;

также хорошо печатает. Итак, я не понимаю, насколько это отличается от желаемого?

Ответ 3

Если вы переопределите метод ToString, это должно сделать.