0

我正在尝试在 PureScript 中编写类似 Redux 的存储。

我为每个动作定义Action了类型类和代数数据类型,以划分为更小的模块。

class Action a

data FooAction
  = UpdateFoo String
  | ResetFoo

data BarAction
  = UpdateBar Int
  | ResetBar

data ResetAll = ResetAll

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

并定义了一些状态类型和更新函数。更新函数可以接收所有类型的动作。

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

但是此代码会产生 TypesDoNotUnify 错误。

  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

为什么会出现这个错误?我应该如何实现这样的更新功能?

4

1 回答 1

0

这里的问题是您正在匹配一个值Action a => a,就好像它是 一样Foo,因此出现类型错误。

如果你想使用类来解决问题,方法是让动作成为类的一部分,而不是不同类型的数据构造函数:

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

然后您可以使用,或您为其实现实例的任何类型值调用updateor 。resetFooBarBazThing

如果问题是您想表示这些东西可以执行的不同操作集,那么您也可以使用子类:

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

我不确定我是否完全理解你在这里想要做什么,所以也许这不是你真正想要的,但希望能给你一些想法。

于 2016-05-09T20:16:03.690 回答