artella
artella

Reputation: 5118

Is is possible to refer to Type Variables in pattern matching?

The following code (which is not meant to do anything useful) compiles fine :

{-# LANGUAGE ScopedTypeVariables #-}
import System.Random

uselessFunction :: (RandomGen g) => g -> [Int]
uselessFunction gen = 
  let (value::Int, newGen) = (random gen)
  in (uselessFunction newGen)

Is it possible for me to use type variables in the pattern matching, in the following spirit (code fails to compile):

{-# LANGUAGE ScopedTypeVariables #-}
import System.Random

uselessFunction :: (RandomGen g, Random a) => g -> [a]
uselessFunction gen = 
  let (value::a, newGen) = (random gen)
  in (uselessFunction newGen)

Upvotes: 4

Views: 253

Answers (2)

Cactus
Cactus

Reputation: 27636

The real way out of this is described in Type Variables in Patterns, by Richard A. Eisenberg, Joachim Breitner, Simon Peyton Jones:

For many years, GHC has implemented an extension to Haskell that allows type variables to be bound in type signatures and patterns, and to scope over terms. This extension was never properly specified. We rectify that oversight here. With the formal specification in hand, the otherwise-labyrinthine path toward a design for binding type variables in patterns becomes blindingly clear. We thus extend ScopedTypeVariables to bind type variables explicitly, obviating the Proxy workaround to the dustbin of history.

Upvotes: 0

Ørjan Johansen
Ørjan Johansen

Reputation: 18199

You've already noticed that the ScopedTypeVariables extension allows you to put type annotations on patterns. But for the extension's main purpose, to make a type variable be locally scoped so that you can refer to it inside the function, you must also declare it with a forall in the type declaration, like so:

uselessFunction :: forall a g. (RandomGen g, Random a) => g -> [a]

This doesn't change the meaning of the declaration itself, but hints to GHC that you may want to use the variable locally.

Upvotes: 8

Related Questions