constructorpattern-matchingsmlalgebraic-data-typesshadowing

SML pattern matching on datatypes with constructors from function arguments


In the example, there is a "match redundant" Error, indicating that SOME s is matching on every string and not the provided s:

fun matchs (s : string) : (string option -> bool) =
  fn x => case x of
        SOME s => true
      | NONE => false
      | _ => false

Is the s in SOME s shadowing the argument s? That is the only explanation I can come up with. If I replace SOME s with SOME "specific string" it works as expected. It is surprisingly hard to find documentation on how this datatype constructor pattern matching works. Somehow I have never encountered this before (or I probably have and forgot).

My original question was about syntactic sugar used by functors, but it seems like this isn't specific to functors.

signature FOO = 
sig
  val f : string option -> bool
end

functor MkFoo (val s : string) :> FOO = 
struct
  fun f x = case x of
      SOME s => true
    | NONE => false
    | _ => false
end

structure NewFoo = MkFoo (val s = "foo")
val false = NewFoo.f (SOME "bad")

Solution

  • In your code:

    fun matchs (s : string) : (string option -> bool) =
      fn x => case x of
            SOME s => true
          | NONE => false
          | _ => false
    

    Pattern-matching SOME s does not mean that the value wrapped in the SOME constructor is equal to s. It simply binds that value to the name s, shadowing the earlier binding of s.

    If you want to do that you need a conditional. A minimal modification of your function might be:

    fun matchs (s : string) : (string option -> bool) =
      fn x => case x of
            SOME s' => s = s'
          | NONE => false
    

    You might also write this more tersely but equivalently as:

    fun matchs (s : string) NONE = false
      | matchs (s : string) (SOME x) = s = x
    

    As you suspect, no this has nothing to do with functors.