Search code examples
purescript

Unifying record type


As a learning exercise, I'm trying to define a newtype to serve as a holder of functions that can convert Show-able values to Effects, i.e.:

newtype ShEff a = ShEff (forall eff. Show a => a -> Eff eff Unit)

However, this:

f :: forall a. ShEff a
f = ShEff logShow

fails to compile with this error:

  Could not match type

    ( console :: CONSOLE
    | t2
    )

  with type

    eff1


while trying to match type Eff
                             ( console :: CONSOLE
                             | t2
                             )
  with type Eff eff1
while checking that expression logShow
  has type t0 -> Eff eff1 Unit
in value declaration f

Can you point me in the right direction?


Solution

  • The type of logShow is

    forall eff. Show a => a -> Eff (console :: CONSOLE | eff) Unit
    

    so you can't store it inside ShEff, since that must work for every eff, and logShow only works for rows containing the CONSOLE effect.

    You have two options:

    1. Move the eff type argument outside ShEff:

      newtype ShEff eff a = ShEff (a -> Eff eff Unit)
      
      f :: forall a eff. Show a => ShEff (console :: CONSOLE | eff) a
      f = ShEff logShow
      
    2. Add the constraint inside ShEff:

      newtype ShEff a = ShEff (forall eff. a -> Eff (console :: CONSOLE | eff) Unit)
      
      f :: forall a eff. Show a => ShEff a
      f = ShEff logShow
      

    Also notice that I've moved the Show a constraint outside ShEff in both cases.