为什么 "not" 关心 SML 中的 "List.exists" 输入?

Why does "not" care about "List.exists" input in SML?

我做了一个函数来识别某个对象是否有重复,如下所示:(PS:测试通过)

(* ListOfPattern -> Pattern -> String List -> List.exists (function) ->  bool*)
val check_pat =
  let 
    fun patternToVars p =
      case p of
        Variable x => [x]
      | TupleP lop => List.foldl (fn (p, acc) => (patternToVars p) @ acc) [] lop
      | _ => []
        
    fun isDuplicated lov =
      case lov of
        [] => false
      | lov::lov' => List.exists (fn prevString => prevString = lov) lov' orelse isDuplicated lov'
  in
    not o isDuplicated o patternToVars 
    (* Cannot understand why `not o` works but `not` does not, duplicate returns bool in all 
        cases and there is no need for piping *)
  end

但是,如果我从 not o isDuplicated o patternToVars 中删除 o 并将其设为 not isDuplicated o patternToVars returns,则会出现以下错误:

Error: operator and operand don't agree [tycon mismatch]
  operator domain: bool
  operand:         ''Z list -> bool
  in expression:
    not isDuplicated

问题是“为什么 isDuplicated 返回列表?”

消息并没有说 isDuplicated returns 是一个列表,而是说 isDuplicated 是一个类型为 ''Z list -> bool 的函数,而你正在尝试当 not 需要 bool 参数时对其应用 not

not o 不是有意义的“单位”; o是二元运算符,f o g等价于fn x => f (g x).

因为函数应用的优先级高于o,

not isDuplicated o patternToVars

等同于

(not isDuplicated) o patternToVars

也就是说,您试图否定函数 isDuplicated,而不是它的结果。

如果您添加参数并嵌套显式函数应用程序,您的特定问题可能会变得更加明显;第一个相当于

fn p => not (isDuplicated (patternVars p))

而第二个相当于

fn p => (not isDuplicated) (patternVars p)

你可以看到非常不同。


再次尝试澄清:

如果我们将组合定义为函数而不是中缀运算符,也许会变得更清楚:

fun compose (f, g) = fn x => f (g x)

甚至

fun compose (f, g) = f o g

然后,

not o isDuplicated o patternToVars

相同
compose (not, compose (isDuplicated, patternToVars))

not isDuplicated o patternToVars

相同
compose (not isDuplicated, patternToVars)