1
votes

Is it reasonable to have multi parameter type classes in PureScript?

The compiler raises an unreasonable 'No type class instance was found' error (see full output) for the below type class definition:

class Transform model turn where
  transform :: turn -> model -> model
  delay :: Maybe turn -> Int

The error arises from the definition of the delay function which doesn't depend on the model type parameter. As evident from the compiler output linked above it substitutes a t0 for the absent model.

What is the proper way to fix this? Currently I workaround this issue by changing the kind of turn as below:

class Turnable model turn where
  runTurn :: turn model -> model -> model
  turnDelay :: Maybe (turn model) -> Int
2

2 Answers

1
votes

rightfold from the FP slack channel gave this answer:

add fundep | turn -> model

Then the instance is looked up only through turn

Consequently I changed the type class definition to this:

class Turnable model turn | turn -> model where
  runTurn :: turn -> model -> model
  turnDelay :: Maybe turn -> Int

This made the compiler happy. For details, consult Functional dependencies (fundep) in the Haskell wiki and the 24 days of PureScript post.

0
votes

...in the old days we had used a Proxy (https://github.com/purescript/purescript-proxy) to help the compiler decide which instance to choose. e.g. :

turnDelay :: Proxy model -> turn -> Int
turnDelay _ turn = .....

and call it by passing in a proxy:

turnDelay (Proxy :: Proxy FooModel) barTurn

I agree FunDeps are the right way to go.