Я изучаю Хаскель трудным путем, пытаясь написать что-то, что мне кажется интересным, и сейчас я пытаюсь выяснить, как получить полукольцо в Хаскеле для определенного набора проблем синтаксического анализа:
class Semiring s where
zero, one :: s
mul, add :: s -> s -> s
instance Semiring Bool where
zero = False
one = True
add = (||)
mul = (&&)
instance Semiring (Set String) where
zero = empty
one = singleton ""
add a b = union a b
mul a b = Data.Set.map (\(c, d) -> c ++ d) $ cartesianProduct a b
Версия Bool ({true, false}, ∨, ∧, false, true) прекрасно работает.Так же как и версия Int.Последний из них называется Parse Forest , и его представление (E, ∪, ·, ∅, {<>}), где E - набор строк, а {<>} - наборпустой строки.
Когда я пытаюсь скомпилировать это, я получаю:
Rigge… 115 10 error • Illegal instance declaration for ‘Semiring (Set String)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Что не имеет для меня особого смысла.Set String
- это отдельный тип, верно, и все операции class Semiring
должны быть выражены исключительно в терминах наборов строк.
Если вам нужен контекст, проект находится на RiggedРегулярные выражения .Версия Bool просто сообщает, что регулярное выражение совпадает;версия Int сообщает количество различных способов сопоставления регулярному выражению (т. е. "a" ~ /(a|a*)/
вернет 2
, поскольку совпадают два отдельных и уникальных подвыражения);ParseForest должен возвращать не количество путей, а набор всех возможных путей - но он не может этого сделать, потому что я не понимаю, почему я не могу использовать конкретный тип данных, Set String
, где другой конкретный тип данныхвроде Int
или Bool
работал нормально.