Estoy intentando escribir un lector de letras básico usando Haskell. Para implementar DFA y NFA, decidí poner algunas funciones comunes en las clases FA y FAState.No hay error de instancia con las clases de parámetros múltiples
-- |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.
donde,
-- |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)]
Por lo tanto, B representa el tipo de datos para el que se producen las transiciones. Para un DFA, b = Char, mientras que para un NFA, b = Símbolo.
data Symbol = Alphabet Char | Epsilon
deriving (Show, Read, Eq)
DFA y NFA se definen respectivamente como:
data DFA = DState Int StateType (Transitions Char DFA)
deriving (Show, Read)
data NFA = NState Int StateType (Transitions Symbol NFA)
deriving (Show, Read)
Estoy teniendo un problema con las definiciones de instancia de FA & FAState:
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
Al intentar ejecutar cualquiera de las funciones obtengo un error sin instancia:
>>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
No entiendo qué está pasando aquí.
También existe el viejo truco de unificación diferida, donde pretendes que un parámetro de tipo es muy genérico y luego se tuerce el brazo de GHC para hacerlo específico una vez que se compromete con una instancia ... pero eso es útil para engañar. –
@ C.A.McCann Ah, sí, buena sugerencia. Lo agregaré –
Antes de publicar la pregunta que leí un poco sobre las dependencias de función, no creo que se aplique a este caso porque no puedo entender cómo el compilador puede deducir el valor de b con a. Me refiero a cómo decir que "b se puede encontrar usando a", ¿ayuda al compilador a encontrar b? – Likhit