Skip to content

type inference fails with where clause (RankNTypes, TypeFamilies)

when using RankNTypes and TypeFamilies with polymorphic functions, type inference works in let but not in where clauses.

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}

import Control.Monad

class Monad m => GenM m where
    type GenReq m :: *

type GenFun a b = forall m. GenM m => a -> m b
data GenDef a b = GenDef { name :: String, fun :: GenFun a b }
data Gen a b = Gen
data Struct = Struct

mkGen :: forall a b. String -> GenFun a b -> GenDef a b
mkGen = GenDef

runGen :: GenM m => Gen a b -> a -> m (Maybe b)
runGen = undefined

getPatients :: GenM m => m [Int]
getPatients = undefined

-- BROKEN
myGen :: Gen String Struct -> GenDef Int [Struct]
myGen structGen =
    mkGen "myGen" $ \pid ->
        do pats <- getPatients
           structs <- mapM patToStruct pats
           return structs
        where
          patToStruct pid =
              do Just struct <- runGen structGen (show pid)
                 return struct

-- WORKS
myGen' :: Gen String Struct -> GenDef Int [Struct]
myGen' structGen =
    mkGen "myGen" $ \pid ->
    do pats <- getPatients
       let patToStruct pid =
               do Just struct <- runGen structGen (show pid)
                  return struct
       structs <- mapM patToStruct pats
       return structs

-- WORKS
myGen'' :: Gen String Struct -> GenDef Int [Struct]
myGen'' structGen =
    mkGen "myGen" $ \pid ->
        do pats <- getPatients
           structs <- mapM patToStruct pats
           return structs
        where
          patToStruct :: GenM m => Int -> m Struct
          patToStruct pid =
              do Just struct <- runGen structGen (show pid)
                 return struct
Edited by Simon Peyton Jones
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information