...Вона блює і співає (bytebuster463) wrote in ru_fsharp,
...Вона блює і співає
bytebuster463
ru_fsharp

Что-то тихо здесь

Посмотрел, что в коммуне слишком тихо, вот и попросился у уважаемого модератора права на запись. Давайте что-то обсудим, что ли. :)
Например, вот что есть в моём скромном маленьком проекте (на вебе уже живёт, но ссылку не даю, во избежание):
  1. Разбор естественного человеческого языка (тайского) с помощью FParsec. Сам автор ФПарсека, Stephan Tolksdorf, сказал, что он никогда не думал, что его детищем могут парсить натуральные языки. Скоро будет также лаосский, камбоджийский, санскрит и деванагари.
  2. Монадическая модель доказательства к логическому выводу, написанная с нуля (советы будут приняты с огромной радостью, ибо написано на коленке).
Про FParsec всё понятно, кроме того, что он используется для нечёткого парсинга, примерно такого же, который используется для парсинга некомпилирующегося кода в проектах типа ReSharper.
Другими словами, производится иерархический парсинг с возвратом до тех пор, пока не будет обнаружен чёткий признак, что парсинг можно прервать. Затем все получившиеся цепочки взвешиваются и выбирается самая "качественная":
val variants: Parser<'T seq> -> Parser<'T list list>
Где на входе список правил, а на выходе список, каждый элемент в котором - упорядоченный список правил, которые могут быть применены ко входному потоку.

Про модель доказательства в двух словах.
Рассматриваем каждую функцию как механизм получения логического вывода. Аргументы - это некоторые аксиомы, поданные на вход ("икс равен пяти"). Функция может обращаться к другим функциям, которые, в свою очередь, тоже делают какие-то выводы по таким же правилам. Моя цель была - провести "трассу" логических выводов сквозь все частные выводы к конечной цели.

Для этого каждая функция возвращает не просто сам по себе результат, а
'TResult * Tree<'TProof>
Где дерево упрощённо выглядит как
Tree<'T> = | Empty | Leaf of 'T | Node of 'T * List<Tree<'T>> 

Цепочка функций сопрягается примерно так:

let increment a = proven "incremented" {
    let! _ = a <!?> "argument a"
    return a+1
    }
 
let mymethod x y = proven "mymethod" {
    let! _ = x <!?> "argument x"
    let! _ = y <!?> "argument y"
    let! x2 = increment x
    let! y2 = increment y
    return x2+y2
    }
 
let result, resultProof = mymethod 5 20

Такой вызов вернёт resultProof, который можно представить в виде:

Goal: mymethod = 27 because
|     (1) argument x = 5
| AND (2) argument y = 20
| AND (3) incremented = 6 because
| |     (3.1) argument a = 5
| AND (4) incremented = 21 because
| |     (4.1) argument a = 20

Оператор <!?> - это shortcut на простой метод 'T -> 'T * Leaf<string>

Да, и ещё. На самом деле, дерево не просто из стрингов состоит, а из Lazy<string>. То есть, само дерево формируется сразу, а логический вывод, который не всегда нужен юзеру, да ещё и активно вызывающий sprintf (который тяжёлый), формируется только тогда, когда мы уже дерево визуализируем в текст или XML.
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments