Ich versuche, einen grundlegenden Lexer mit Haskell zu schreiben. Für die Umsetzung des EDA und des NFA habe ich beschlossen, einige allgemeine Funktionen in die Klassen FA und FAState zu integrieren.Kein Fehler mit mehreren Parameterklassen
-- |A class for defining the common functionality of all finite automatons.
class FA a b where
mutateId :: a -> Int -> a -- ^Returns a new FA by changing the sId of the input FA.
mutateType :: a -> StateType -> a -- ^Returns a new FA by changing the stateType of the input FA.
addTransition :: a -> (b, a) -> a -- ^Returns a new FA by adding a new transition to the input FA.
-- |A class for defining the common functionality of all finite automaton states.
class FA a b => FAState a b where
sId :: a -> Int -- ^An unique identifier for the state(hence the prefix s).
sType :: a -> StateType -- ^The type of the state.
sTransitions :: a -> Transitions b a -- ^The transitions that occur from this state.
wo
-- |A type which identifies different types of a FA state.
data StateType = Start | Normal | Final
deriving (Show, Read, Eq)
-- |A type which represents a list of transitions on input a to b.
-- Eg. [(Char, DFA)] represents the transition on a Char input.
type Transitions a b = [(a, b)]
Daher stellt B den Datentyp, für die Übergänge auftreten. Für ein DFA ist b = Char, während für ein NFA b = Symbol ist.
data Symbol = Alphabet Char | Epsilon
deriving (Show, Read, Eq)
DFA und NFA sind jeweils wie folgt definiert:
data DFA = DState Int StateType (Transitions Char DFA)
deriving (Show, Read)
data NFA = NState Int StateType (Transitions Symbol NFA)
deriving (Show, Read)
Ich bin ein Problem mit den Instanzdefinitionen von FA & FAState mit: von laufen
instance FA DFA Char where
mutateId (DState i ty ts) new_i = DState new_i ty ts
mutateType (DState i ty ts) new_ty = DState i new_ty ts
addTransition (DState i ty ts) state = DState i ty (state:ts)
instance FAState DFA Char where
sId (DState i t ts) = i
sType (DState i t ts) = t
sTransitions (DState i t ts) = ts
instance FA NFA Symbol where
mutateId (NState i ty ts) new_i = NState new_i ty ts
mutateType (NState i ty ts) new_ty = NState i new_ty ts
addTransition (NState i ty ts) state = NState i ty (state:ts)
instance FAState NFA Symbol where
sId (NState i t ts) = i
sType (NState i t ts) = t
sTransitions (NState i t ts) = ts
Beim Versuch irgend die Funktionen bekomme ich einen keine Instanz Fehler:
>>sId egNFA
<interactive>:15:1:
No instance for (FAState NFA b0)
arising from a use of `sId'
Possible fix: add an instance declaration for (FAState NFA b0)
In the expression: sId egNFA
In an equation for `it': it = sId egNFA
Ich verstehe nicht, was hier passiert.
Es gibt auch den alten verzögerten Unifikationstrick, bei dem du vorgibst, ein Typparameter sei sehr generisch und verdrehst dann GHC's Arm, um es spezifisch zu machen, sobald es sich auf eine Instanz festlegt ... aber das ist meistens nützlich für anrüchige Shenanigans. –
@ C.A.McCann Ah, ja, guter Vorschlag. Ich werde es hinzufügen. –
Bevor ich die Frage geschrieben habe, habe ich ein wenig über Funktionsabhängigkeiten gelesen, ich dachte nicht, dass es für diesen Fall zutrifft, weil ich nicht verstehen kann, wie der Compiler den Wert von b mit a ableiten kann. Ich meine, wie sagt das, dass "b mit Hilfe von a herausgefunden werden kann", hilft dem Compiler tatsächlich, b zu finden? – Likhit