我使用wl-pprint包,因为标准的 PrettyPrinter 缺乏功能。一切都很好,除了vcat
函数中的空文档(与<$>
组合器相同)。
正确行为:
import Text.PrettyPrint
> vcat[text "a", empty, text "b"]
a
b
Run Code Online (Sandbox Code Playgroud)
wl-pprint 显示一个额外的空行:
import Text.PrettyPrint.Leijen
> vcat[text "a", empty, text "b"]
a
b
Run Code Online (Sandbox Code Playgroud)
那我能做什么?这是IMPOSIBLE进行筛选VCAT列表中,因为没有Eq
为实例Doc
。
为什么这会引发关于减少/减少冲突的警告
root : set1 'X'
| set2 'X' 'X'
set1 : 'A'
| 'B'
set2 : 'B'
| 'C'
Run Code Online (Sandbox Code Playgroud)
但接下来还可以吗?
root : 'A' 'X'
| 'B' 'X'
| 'B' 'X' 'X'
| 'C' 'X' 'X'
Run Code Online (Sandbox Code Playgroud) 我知道,我们不能独立实现IO monad,但我不知道为什么.此代码试图使用函数式语言实现命令式范例.你能解释一下这个例子和真正的IO之间的区别吗?看起来函数main实现了正确的动作顺序并且仍然是懒惰的.
import System.IO.Unsafe
data Io a = Io a
runIO :: Io a -> a
runIO (Io a) = a
instance Monad Io where
return x = Io x
Io a >>= f = f a
-- internal side effect function
output :: Show a => a -> Io ()
output s = return $! unsafePerformIO $ print s
----------------------------------------------------------------
mainIO :: Io ()
mainIO = do output "A"
b <- return "B"
output b
output b
x <- …
Run Code Online (Sandbox Code Playgroud) 如何为解析if-then [-else]案例制定正确的规则?这是一些语法:
{
module TestGram (tparse) where
}
%tokentype { String }
%token one { "1" }
if { "if" }
then { "then" }
else { "else" }
%name tparse
%%
statement : if one then statement else statement {"if 1 then ("++$4++") else ("++$6++")"}
| if one then statement {"if 1 then ("++$4++")"}
| one {"1"}
{
happyError = error "parse error"
}
Run Code Online (Sandbox Code Playgroud)
该语法正确解析以下表达式:
> tparse ["if","1","then","if","1","then","1","else","1"]
"if 1 then (if 1 then (1) else (1))"
Run Code Online (Sandbox Code Playgroud)
但编译会引发关于转移/减少冲突的警告.happy的文档包含了这种冲突的一个例子:http …
我已经问过关于undefined的问题.而且因为不可能做这样的事情,我将描述这个有用的情况.但我认为这个问题很常见,在其他情况下也很有用.
让我们想象一下当我们为某些语法编写解析器时的情况.我们定义了由许多数据类型实现的AST,每个数据类型都有一组构造函数,每个构造函数都有一组参数.每种类型都来自Show.然后我们开始编写解析器实现,其中我们定义了许多具有递归依赖性的函数.
由于我们有很多功能,因此很难在没有检查的情况下立即编写整个模块.但函数循环引用将不允许编译未完成的模块.在这种情况下,我定义了钩子函数,它们不需要返回所需类型的返回值.
这是一个问题!函数必须返回不是简单类型,而是返回构造函数中带有构造函数的数据构造函数.这对于钩子函数来说太难了.所以我这样做:
parseHook _ = undefined
Run Code Online (Sandbox Code Playgroud)
一切都很简单,直到"undefined"不在结果数据树中.我想指出,这种情况发生在开发阶段,我唯一想要的是看到树结构.当然,我可以在"Maybe"中包装每种类型,但我不想更改已有的类型.
英语不是我的母语,所以我不确定我是否正确表达了我的想法.这就是我想添加这种情况的一个例子的原因:
data StructParam = StructParam Int Int
deriving Show
data Struct1 = Struct1 Int Int StructParam Int Int Int Int StructParam
deriving Show
data Struct2 = Struct2 Int Int StructParam Int Int Int Int StructParam
deriving Show
data Struct3 = Struct3_var1 Struct1
| Struct3_var2 Struct2
deriving Show
-- this hook is ok, but too long
parse1 _ = Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam …
Run Code Online (Sandbox Code Playgroud)