When there's a definition like:
parseJSON :: forall a. (ReadForeign a) => String -> Either String a
parseJSON json = fromString json >>= parseForeign read
where
fromString :: String -> Either String Foreign
fromString = runFn3 fromStringImpl Left Right
As fromString doesn't use any variables introduced by parseJSON it can be treated as:
parseJSON :: forall a. (ReadForeign a) => String -> Either String a
parseJSON json = fromString json >>= parseForeign read
fromString :: String -> Either String Foreign
fromString = runFn3 fromStringImpl Left Right
As otherwise, in the generated JS, whenever parseJSON is called you also have to pay for the creation of fromString every time:
var parseJSON = function (__dict_ReadForeign_0) {
return function (json) {
var fromString = Data_Function.runFn3(fromStringImpl)(Data_Either.Left.create)(Data_Either.Right.create);
return Prelude[">>="](Data_Either.bindEither({}))(fromString(json))(parseForeign(read(__dict_ReadForeign_0)));
};
};
This applies anywhere a let or where introduces a function "later" than it needs to, just need to make sure that when moving fromString up its name doesn't conflict with another declaration in the scope it is moved to.
When there's a definition like:
As fromString doesn't use any variables introduced by parseJSON it can be treated as:
As otherwise, in the generated JS, whenever
parseJSONis called you also have to pay for the creation offromStringevery time:This applies anywhere a
letorwhereintroduces a function "later" than it needs to, just need to make sure that when movingfromStringup its name doesn't conflict with another declaration in the scope it is moved to.