Markus Barthlen Markus Barthlen - 2 months ago 16
React JSX Question

Node.js effects in Thermite for Electron

I am trying to expand https://github.com/kRITZCREEK/electron-apps-with-purescript to add an input for the directory whose filenames I would display.

However, I cannot get the following function to typecheck (the last two lines are problematic, the last is line 53):

performAction :: T.PerformAction _ State _ Action
performAction (SetEditText s) _ _ = void do
T.cotransform $ _ { dir = s }
performAction (UpdateFiles s) _ _ = void do
filenames <- either (const []) id <$> try (readdir s)
T.cotransform $ _ { names = filenames }


Here readdir is from Node.FS.Sync and has the signature

forall eff. String -> Eff (fs :: FS, err :: EXCEPTION | eff) (Array String)


and performAction is of type

forall t39 t40. Action -> t40 -> {dir :: String, names :: Array String} -> FreeT (CoTransform (Maybe {dir :: String, names :: Array String}) ({dir :: String, names :: Array String} -> {dir :: String, names :: Array String}))


The actual error is

Could not match type at line 53 col 4

FreeT
(CoTransform t2
({ files :: t3
| t4
}
-> { files :: Array String
| t4
}
)
)
with type
Eff
while trying to match type FreeT
(CoTransform t2
({ files :: t3
| t4
}
-> { files :: Array String
| t4
}
)
)
t5
with type Eff
( fs :: FS
| t0
)
while checking that expression (apply cotransform) (\$1 ->
$1 { files = f
}
)
has type Eff
( fs :: FS
| t0
)
t1
in value declaration performAction
where t1 is an unknown type
t0 is an unknown type
t2 is an unknown type
t5 is an unknown type
t4 is an unknown type
t3 is an unknown type


(The whole project can be found under https://github.com/MarkusBarthlen/electron-apps-with-purescript/blob/master/src/Main.purs)

I suspect I have to use any of lift/liftEff/liftEff'/liftAff. However,

performAction :: T.PerformAction _ State _ Action
performAction (UpdateFiles s) _ _ = void do
filenames <- ( lift (either (const []) id <$> try (readdir s)))
T.cotransform $ _ { names = filenames }


results in

Could not match type at line 55 col 47
Eff
with type
Aff
while trying to match type Eff
( fs :: FS
| t1
)
with type Aff t0

Answer

You can make it work with:

performAction :: forall e. T.PerformAction (fs :: FS | e) State _ Action
performAction (SetEditText s)           _ _ = void do
  T.cotransform $ _ { dir = s }
performAction (UpdateFiles s)           _ _ = void do
   filenames <- lift (liftEff (either (const []) id <$> try (readdir s)))
   T.cotransform $ _ { names = filenames }
  -- T.cotransform $ _ { dir = ""}

liftEff takes your Eff to an Aff and lift then raises that into the FreeT ... that Thermite uses. The extra lift shouldn't be necessary, but I think the problem is type inference around rows and typeclasses here and the situation should get better with the next release where we'll most likely have functional dependencies.

Comments