ndmitchell / record-dot-preprocessor

A preprocessor for a Haskell record syntax using dot
Other
129 stars 19 forks source link

Adding -pgmF=record-dot-preprocessor causes previously compiling code to no longer type-check #39

Closed mfussenegger closed 3 years ago

mfussenegger commented 3 years ago

First of all, thanks for this and the work on the RecordDotSyntax proposal.

I wanted to use this in a project and after adding the preprocessor I get a compile error that I can't explain. I tried to create a minimal reproduction:

{-# OPTIONS_GHC -F -pgmF=record-dot-preprocessor #-}

module Main where

import Prelude hiding (lookup)

type Param = (String, String)

data Job = Job
  { service :: String,
    branch :: String,
    commit :: String,
    pr :: Maybe String,
    build :: Maybe String
  }
  deriving (Eq, Show)

head' :: [a] -> Maybe a
head' [] = Nothing
head' (a : _) = Just a

paramsToJob :: [Param] -> Either String Job
paramsToJob params' =
  let lookup policy name = policy name $ map snd $ filter ((==) name . fst) params'
      service = lookup required "service"
      branch = lookup required "branch"
      commit = lookup required "commit"
      pr = lookup optional "pr"
      build = lookup optional "build"
      optional _ = Right . head'
      required name [] = Left $ "Parameter `" <> name <> "` is required"
      required _ (x : _) = Right x
   in Job <$> service <*> branch <*> commit <*> pr <*> build

main :: IO ()
main = putStrLn "Hello"

With the {-# OPTIONS_GHC -F -pgmF=record-dot-preprocessor #-} this fails with type check errors:

app/Main.hs:28:19: error:
    • Couldn't match type ‘Maybe String’ with ‘[Char]’
      Expected type: String -> [String] -> Either [Char] String
        Actual type: String -> [String] -> Either [Char] (Maybe String)
    • In the first argument of ‘lookup’, namely ‘optional’
      In the expression: lookup optional "pr"
      In an equation for ‘pr’: pr = lookup optional "pr"
   |
28 |       pr = lookup optional "pr"
   |                   ^^^^^^^^

When {-# OPTIONS_GHC -F -pgmF=record-dot-preprocessor #-} is removed the code compiles.

I'm using ghc 8.10.4 and installed the record-dot-preprocessor using stack install record-dot-preprocessor

ndmitchell commented 3 years ago

Thanks for the report. It turns out, given that file, {-# LANGUAGE TypeFamilies #-} alone also makes it fail - nothing to do with RecordDotPreprocessor, other than the fact it happens to use TypeFamilies under the hood. I suggest you turn on TypeFamilies, and fix the errors. And the error is likely to be that TypeFamilies made the function lookup become monomorphic - give it a polymorphic type signature and you should be fine.

mfussenegger commented 3 years ago

Oh that was quick. Thank you for taking the time to look into this.

  • give it a polymorphic type signature and you should be fine.

That worked 👍

I wasn't aware that TypeFamilies would have this effect. I guess it's time for me to learn more about that extension.