Search code examples
gf

Applying Predef.eqStr: Expected a value of type string


I was trying to write an operation that takes an undetermined amount of parameters, so if a user chooses not to fill one of the parameters then the operator changes its functionality.

oper
    gen_NP = overload{
        gen_NP : N -> NP =
            \noun ->
                  mkNP(noun);

        gen_NP : Str -> N -> NP =
            \mdfir, noun ->
                  mkNP(mkN(mdfir) (noun));
        ....
}

But writing in this method would generate a huge number of overload with each new undetermined parameter. So I used this method

oper
        gen_NP : {noun : N ; mdfir : Str ; ....} -> NP =
            \obj
                case eqStr (obj.mdfir) ("") of {
                    PFalse =>
                          mkNP(mkN(mdfir) (noun));
                    PTrue =>
                          mkNP(noun);
                };

}

When I tried the second method the program keep reporting: Applying Predef.eqStr: Expected a value of type String, got VP (VGen 1 []) (LIdent(Id{rawId2utf8 = "mdfir"}))

Is there's a way to fix this problem, or is there's a better way to deal with an undetermined number of parameters?

Thank you


Solution

  • Best practices for overloading opers

    A huge number of overloads is the intended way of doing things. Just look at any category in the RGL synopsis, you see easily over 20 overloads for a single function name. It may be annoying to define them, but that's something you only need to do once. Then when you use your overloads, it's much nicer to use them like this:

    myRegularNoun = mkN "dog" ;
    myIrregNoun = mkN "fish" "fish" ;
    

    rather than being forced to give two arguments to everything:

    myRegularNoun = mkN "dog" "" ;
    myIrregNoun = mkN "fish" "fish" ;
    

    So having several mkN instances is a feature, not a bug.

    How to fix your code

    I don't recommend using the Predef functions like eqStr, unless you really know what you're doing. For most cases when you need to check strings, you can use the standard pattern matching syntax. This is how to fix your function:

    oper
      gen_NP : {noun : N ; mdfir : Str} -> NP = \obj ->
        case obj.mdfir of {
          "" => mkNP obj.noun ;
          _ => mkNP (mkN obj.mdfir obj.noun)
        } ;
    

    Testing in the GF shell, first with mdfir="":

    > cc -unqual -table gen_NP {noun = mkN "dog" ; mdfir = ""}
    s . NCase Nom => dog
    s . NCase Gen => dog's
    s . NPAcc => dog
    s . NPNomPoss => dog
    a . AgP3Sg Neutr
    

    And now some non-empty string in mdfir:

    > cc -unqual -table gen_NP {noun = mkN "dog" ; mdfir = "hello"}
    s . NCase Nom => hello dog
    s . NCase Gen => hello dog's
    s . NPAcc => hello dog
    s . NPNomPoss => hello dog
    a . AgP3Sg Neutr