为什么这个类型的实例无法统一?

时间:2016-05-09 05:52:37

标签: types purescript

我正在尝试用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

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

1 个答案:

答案 0 :(得分:0)

此处的问题是您在值Action a => a上匹配,就像它是Foo一样,因此类型错误。

如果要使用类来解决问题,那么方法是将操作作为类的一部分,而不是不同类型的数据构造函数:

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

然后,您可以使用updateresetFoo或您实施{{1}的任何类型值来致电BarBaz } instance for。

如果问题是你要表示这些事情可以执行的不同操作集,那么你也可以使用子类:

Thing

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