我正在写一个迷你语言,我遇到了一个情况,我试图处理一个抽象的语法树,这样它要么返回一个异常,要么返回一个将解析为bool的函数。下面是一个简单的例子:
data MyException = Can'tResolveToBool
data InputToBeAddedLater =
InputToBeAddedLater String
data Exp a =
ReturnsBoolFunc String (Exp a)
| IsBool Bool
| ReturnsExpFunc String (Exp a)
resolveToExp :: String -> Exp a -> (InputToBeAddedLater -> Exp a)
resolveToExp funcName arg
| funcName == "patently_false" = (\_ -> IsBool False)
resolveToBool :: Exp a -> Either MyException Bool
resolveToBool (ReturnsBoolFunc funcName (ReturnsExpFunc fn arg)) =
let resolved = resolveToExp fn arg
in case resolved of
((InputToBeAddedLater _) -> (IsBool bool)) -> Right bool
((InputToBeAddedLater _) -> (ReturnsExpFunc _ _)) -> Left Can'tResolveToBool
字符串
最后一行是我(可悲的是,非功能性的)尝试在函数类型上进行模式匹配。GHC建议我尝试ViewPatterns
扩展,但简单地看一下,我不确定这是我需要的。在概念上是不可能做到我在这里尝试做的事情吗?
谢谢你,谢谢
3条答案
按热度按时间bn31dyow1#
让我们戏剧性地简化这个问题。这是你问题的核心:我可以实现
desired
吗?字符串
希望所有的谷壳都被筛掉,很明显,这是不可能做到的:关于
f
是否返回True
或False
,不一定存在事实。它返回的值可以取决于你传递给它的输入!j2cgzkjk2#
据我所知,你想用这种模式表达什么
字符串
是检查
resolved
是否返回 * 任何输入 * 与外部构造函数IsBool
的东西。即是否为型
由于非严格性,您至少可以 * 验证 *,而无需提供具体的
i
:型
这样做的问题是,如果
resolved
在提供外部构造函数之前实际计算了它的参数,那么它就会崩溃,例如型
您现在可以在此基础上添加一些错误捕获机制,但这只能在IO中完成,而且无论如何都是很麻烦的。
实际上,我认为这是一个XY问题,实际上应该做的是给予
resolved
一种方法,在没有任何输入的情况下通知其结果的外部构造函数。这可以通过泛化Exp
来实现,因此它 * 包含 *InputToBeAddedLater
,但只有在揭示最外面的构造函数之后:型
bf1o4zei3#
作为一般的答案,可以在一些函数上进行模式匹配,像
(Tag ->)
这样的可表示函子同构于Vector 3
:字符串