haskellfrege

How to define multiple patterns in Frege?


I'm having some trouble defining a function in Frege that uses multiple patterns. Basically, I'm defining a mapping by iterating through a list of tuples. I've simplified it down to the following:

foo :: a -> [(a, b)] -> b
foo _ [] = [] --nothing found
foo bar (baz, zab):foobar
 | bar == baz = zab
 | otherwise  = foo bar foobar

I get the following error:

E morse.fr:3: redefinition of `foo` introduced line 2

I've seen other examples like this that do use multiple patterns in a function definition, so I don't know what I'm doing wrong. Why am I getting an error here? I'm new to Frege (and new to Haskell), so there may be something simple I'm missing, but I really don't think this should be a problem.

I'm compiling with version 3.24-7.100.


Solution

  • This is a pure syntactical problem that affects newcomers to languages of the Haskell family. It won't take too long until you internalize the rule that function application has higher precedence than infix expression.

    This has consequences:

    In Frege, in addition, the following rule holds:

    The syntax of function application and infix expressions on the left hand side of a definition is identical to the one on the right hand side as far as lexemes allowed on both sides are concerned. (This holds in Haskell only when @ and ~ are not used.)

    This is so you can define an addition function like this:

    data Number = Z | Succ Number
    
    a + Z      = a
    a + Succ b = Succ a + b
    

    Hence, when you apply this to your example, you see that syntactically, you're going to redefine the : operator. To achieve what you want, you need to write it thus:

    foo bar ((baz, zab):foobar) = ....
    --      ^                 ^
    

    This corresponds to the situation where you apply foo to a list you are constructing:

    foo 42 (x:xs)
    

    When you write

    foo 42 x:xs
    

    this means

    (foo 42 x):xs