1

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")
3
  • Yes, variable patterns are irrefutable (and in this case the binding shadows the earlier one). In Haskell or OCaml you would use a guard for this, but it doesn't seem like SML supports those (see stackoverflow.com/questions/60086330/…), so perhaps you just have to use an if statement. Commented Jun 11 at 21:50
  • What does irrefutable mean here? That the datatype constructor always acts like a val/fun declaration? Commented Jun 11 at 22:24
  • 1
    It means that the pattern s always matches. (Of course, SOME s does not always match, but the s itself doesn't impose any further restrictions on the argument of SOME.) Commented Jun 11 at 22:56

1 Answer 1

0

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.

Also note that you've typed matchs as working on strings specifically, but there's no reason this couldn't be polymorphic.

fun matchs _ NONE = false
  | matchs s (SOME x) = s = x
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, I thought of the curried thing after I posted. But I didn't get around to editing it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.