0

I am trying to write Redux-like store in PureScript.

I defined Action type class and algebraic data types for each actions to divide to smaller modules.

class Action a

data FooAction
  = UpdateFoo String
  | ResetFoo

data BarAction
  = UpdateBar Int
  | ResetBar

data ResetAll = ResetAll

instance fooAction :: Action FooAction    
instance barAction :: Action BarAction

And defined some state types and update functions. The update functions may receive all types of actions.

newtype Foo = Foo String
newtype Bar = Bar Int

updateFoo :: forall a. (Action a) => a -> Foo -> Foo
updateFoo a foo =
  case a of
    UpdateFoo str -> Foo str
    ResetFoo      -> Foo ""
    ResetAll      -> Foo ""
    _             -> foo

updateBar :: forall a. (Action a) => a -> Bar -> Bar
updateBar a bar =
  case a of
    UpdateBar num -> Bar num
    ResetBar      -> Bar 0
    ResetAll      -> Bar 0
    _             -> bar

But this code produces TypesDoNotUnify error.

  Could not match type

    FooAction

  with type

    a0


while checking that expression case a of
                                 (UpdateFoo str) -> Foo str
                                 ResetFoo -> Foo ""
                                 ResetAll -> Foo ""
                                 _ -> foo
  has type Foo
in value declaration updateFoo

where a0 is a rigid type variable

Why is this error occurred? And how should I implement update functions like this?

katashin
  • 33
  • 5

1 Answers1

0

The problem here is you're matching on a value Action a => a as if it is Foo, hence the type error.

If you want to use classes to solve the problem, the approach would be to make the actions part of the class, rather than data constructors of differing types:

class Thing a
  update :: a -> String
  reset :: a -> Unit

And then you could call update or reset with a Foo , Bar, Baz or whatever typed value that you implement a Thing instance for.

If the problem is you want to represent different sets of operations that these things can perform, then you can use a subclass too:

class Thing a <= SubThing a
  act :: a -> Unit

I'm not sure I quite understand what you're trying to do here though, so perhaps this isn't really what you're after, but hopefully will give you some ideas.

gb.
  • 4,629
  • 1
  • 20
  • 19