Haskell全新并尝试编写解析器。
我已经使用attoparsec成功地将输入文件切换为令牌到AST中。
我现在想要走AST并从中发出输出。我想我可以通过从类型类派生一些通用例程到Token类来实现,然后在实例中根据Token类型发出代码时需要提供特定函数。
代码可能比我的解释更容易理解。这就是我试过的:
class AST a where
children :: a -> [a]
prefix :: a -> String
suffix :: a -> String
node :: a -> [String]
children v = []
prefix v = ""
suffix v = ""
node v = [prefix v] ++ (concatMap node $ children v) ++ [suffix v]
data Token = Line { lnName :: String, lnLines :: Int }
| LineList { llLines :: [Token] }
| Init String
| Main String
| Step { stId :: String, stDuration :: Float }
| Scene { scId :: String, scTokens :: [Token] }
| Sequence { sqId :: String , sqScenes :: [Token] }
| File {flContents :: [Token]} deriving (Show, AST)
所以我的理解是,如果我从我写过的类型类派生出来:
但是我从ghc那里得到的错误并不是那么有用
Parser.hs | 27 col 60错误|无法使
AST Token':
AST'的派生实例不是可派生类在“令牌”的数据声明中
足够公平,但为什么会这样呢?如何在没有任何更多信息的情况下修复它有点不知所措。任何帮助都感激不尽。
我知道这不是一个有用的评论,但我必须说,绝对爱Haskell。学习是一种快乐:)
答案 0 :(得分:5)
deriving
可用于limited, fixed list of typeclass。这里的问题是你需要告诉编译器你定义的函数是数据类型AST
的类Token
的实例,如下所示:
class AST a where
children :: a -> [a]
prefix :: a -> String
suffix :: a -> String
node :: a -> [String]
instance AST Token where
children v = []
prefix v = ""
suffix v = ""
node v = [prefix v] ++ (concatMap node $ children v) ++ [suffix v]
data Token = Line { lnName :: String, lnLines :: Int }
| LineList { llLines :: [Token] }
| Init String
| Main String
| Step { stId :: String, stDuration :: Float }
| Scene { scId :: String, scTokens :: [Token] }
| Sequence { sqId :: String , sqScenes :: [Token] }
| File {flContents :: [Token]}
deriving (Show)
答案 1 :(得分:2)
感谢Nicolas的解释,派生只适用于一组特定的类型,我已经解决了我的问题。我的解决方案与Nicolas的解决方案略有不同,因为我仍然可以在AST中保留通用功能,而不是将其绑定到令牌
class AST a where
children :: a -> [a]
prefix :: a -> String
suffix :: a -> String
node :: a -> [String]
children _ = []
prefix _ = ""
suffix _ = ""
node v = [prefix v] ++ (concatMap node $ children v) ++ [suffix v]
data Token = Line { lnName :: String, lnLines :: Int }
| LineList { llLines :: [Token] }
| Init String
| Main String
| Step { stId :: String, stDuration :: Float }
| Scene { scId :: String, scTokens :: [Token] }
| Sequence { sqId :: String , sqScenes :: [Token] }
| File {flContents :: [Token]} deriving (Show )
instance AST token where
-- per token overides added here
-- defaults run if none supplied
谢谢大家