1

I have a line of code where I'm trying to assign a variable (I know haskell doesn't really have variables, but I'm not sure what else to call it) with the minimum element found by using the minimumBy builtin, but I get the following error:

Illegal type signature: `(x', y', z')'
      Type signatures are only allowed in patterns with ScopedTypeVariables
   |
   |     ed1 :: (x', y', z') = minimumBy (comparing (\(_, _, z) -> z)) e

Here is the code.

alg' pr pq nE (G c d) = alg' (ve1 : pr) (ed1 : pq) (nE - 1) (G c d)
    where
   
    e = -- helper function that compiles, but with a wrong value so I omitted it.

    ed1 :: (x', y', z') = minimumBy (comparing (\(_, _, z) -> z)) e

Thank you very much.

winnie33
  • 27
  • 4

1 Answers1

3

Assuming the x', y', z' variables are declared in the outer scope, you need to enable the ScopedTypeVariables annotations. You didn't specify the type signature of the enclosing alg' function in your question, so we'll just pretend it looks like this for the moment.

alg' :: (x', y', z') -> (x', y', z')
alg' (x, y, z) = (x, y, z)
    where ed1 = (x, y, z)

If we want to give ed1 an explicit type signature, it needs to know about the type variables from the outer scope. To this end, we first need to enable a compiler extension. This line needs to be at the very top of your file.

{-# LANGUAGE ScopedTypeVariables #-}

Second, we need to clarify to the compiler that we intend these variables be scoped, as follows.

alg' :: forall x' y' z'. (x', y', z') -> (x', y', z')
alg' (x, y, z) = (x, y, z)
    where ed1 :: (x', y', z')
          ed1 = (x, y, z)

You needn't use forall everywhere, even with ScopedTypeVariables on, but you must use it for any variables you intend to use in an inner scope.

Also, as a general piece of advice, forall is unfortunately an overloaded keyword and is used to mean three different things in ScopedTypeVariables, RankNTypes, and ExistentialQuantification. So if you happen to see forall in the wild, be sure to check what extensions are enabled on that file, as it could be doing something different in that case.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • 1
    I don't know how you answered my question now that I see how poorly I worded it, but you did. Thank you very much – winnie33 Feb 18 '21 at 04:34
  • 1
    I was going to give the same answer but I wasn't sure if you want to pattern match against the tuple or declare it's type. Glad you got your solution and bit more knowledge on Haskell. – pedrofurla Feb 18 '21 at 04:41
  • On the subject of pattern binding, what does this mean in basic haskell code? prod @ (p', q', r') – winnie33 Feb 18 '21 at 16:18
  • @winnie33: It’s called an “‘as’ pattern”. See [What does the “@” symbol mean in reference to lists in Haskell?](https://stackoverflow.com/q/1153465/246886) and [In Haskell, what could `this@(Sentence string _) = do` mean?](https://stackoverflow.com/q/15278980/246886)—the [Haskell Report §3.17.1 Pattern Matching](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-580003.17) explains that `name@pattern` means: match `pattern` and also assign the whole match to `name`. If you don’t know some syntax, the Report is a good place to check first, since it defines the base language. – Jon Purdy Feb 18 '21 at 19:43