我试图在Idris中创建一个函数,如下所示:
strSplit : String -> Maybe (Char, String)
这将是“不合情理的”。将字符串放入其第一个Char
和字符串的其余部分,如果它是空的,则返回Nothing
。
所以我写了这篇文章,但失败了:
strSplit x = case strM of
StrNil => Nothing
StrCons c cd => Just (c, cs)
所以我尝试了这个,有点像Prelude.Strings
:
strSplit x with (strM x)
strSplit "" | StrNil = Nothing
strSplit (strCons c cs) | (StrCons c cs) = Just (c, cs)
编译并运行没有任何问题。
我的问题是,为什么我必须使用with
规则以这种方式拆分字符串,为什么我的原始方法会失败?
注意:很抱歉,我目前无法访问翻译,因此我无法在此处撰写错误消息。
答案 0 :(得分:4)
这里有两个问题。首先,在'case'块中,参数是strM
而不是strM x
,因为它在'with'块中,所以你正在检查不同的东西。
但是有一个更有趣的问题,那就是如果你尝试修复第一个问题:
strSplit : String -> Maybe (Char, String)
strSplit x = case strM x of
StrNil => Nothing
StrCons c cd => Just (c, cs)
你会得到一个不同的错误(这是来自当前的主人,它有重写的错误信息):
Type mismatch between
StrM "" (Type of StrNil)
and
StrM x (Expected type)
因此,'case'和'with'之间的区别在于'with'考虑到您正在检查的事物可能会影响左侧的类型和值。在'case'中,匹配strM x意味着x 必须为“”,但“case”可以出现在任何地方,并且不考虑对其他参数类型的影响(制定适当的对此类型检查规则将是一个非常大的挑战......)。
另一方面,'with'只能出现在顶层:实际上它正在做的是添加另一个顶级的东西来匹配,作为顶级,可以影响类型和其他模式的价值。
所以,简短的回答是'with'支持依赖模式匹配,但'case'不支持。