3

假设我们有三个对象:

MainObj {
  someProp: false
  toggleSomeProp: function () {
    if (this.someProp)
      this.someProp = false
    else
      this.someProp = true
  }
  ...
}

FirstObj {
  someOtherProp: ...
  doSomethingWithOtherProp: function () {...}
  ...
}

SecondObj {
  state: null
  setState: function (s) {
    this.state = s
  }
  getState: function() {
    return this.state
  }
  ...
}

FirstObj并使用自己的属性和方法SecondObj继承someProp和扩展它。使用可以是任何东西的 state 属性(和 get/set 方法)进行扩展。toggleSomePropMainObjSecondObjMainObj

假设我们有两个对象FirstObjSrcSecondObjSrc它们都有getObj方法。第一个返回FirstObj,第二个返回SecondObj

这就是我看到它在 Purescript 中实现的方式:

foreign import data ObjEff :: * -> !
foreign import data Obj :: *
foreign import data FirstObjSrc :: *
foreign import data SecondObjSrc :: *

foreign import somePropImpl :: forall a s e. a -> Eff (oe :: ObjEff s | e) Boolean
foreign import toggleSomePropImpl :: forall a s e. a -> Eff (oe :: ObjEff s | e) Unit

foreign import someOtherPropImpl :: ...
foreign import doSomethingWithOtherPropImpl :: ...

foreign import getStateImpl :: forall a b s e. (a -> Maybe a) -> Maybe a -> b -> Eff (oe :: ObjEff s | e) (Maybe s)
foreign import setStateImpl :: forall a s e. a -> s -> Eff (oe :: ObjEff s | e) Unit


foreign import getFirstObjImpl :: forall a s e. FirstObjSrc -> Eff (oe :: ObjEff s | e) a
foreign import getSecondObjImpl :: forall a s e. SecondObjSrc -> Eff (oe :: ObjEff s | e) a


class MainObj a where
  someProp :: forall s e. a -> Eff (oe :: ObjEff s | e) Boolean
  toggleSomeProp :: forall s e. a -> Eff (oe :: ObjEff s | e) Unit

class FirstObj a where
  someOtherProp :: ...
  doSomethingWithOtherProp :: ...

class (MainObj a) <= SecondObj a where
  getState :: forall s e. a -> Eff (oe :: ObjEff s | e) (Maybe s)
  setState :: forall s e. a -> s -> Eff (oe :: ObjEff s | e) Unit

class ObjSrc a where
  getObj :: forall b s e. a -> Eff (oe :: ObjEff s | e) b


instance objIsMainObj :: MainObj Obj where
  someProp = somePropImpl
  toggleSomeProp = toggleSomePropImpl

instance objIsFirstObj :: FirstObj Obj where
  someOtherProp = someOtherPropImpl
  doSomethingWithOtherProp = doSomethingWithOtherPropImpl

instance objIsSecondObj :: SecondObj Obj where
  getState = getStateImpl Just Nothing
  setState = setStateImpl

instance firstObjSrcIsObjSrc :: ObjSrc FirstObjSrc where
  getObj = getFirstObjImpl

instance secondObjSrcIsObjSrc :: ObjSrc SecondObjSrc where
  getObj = getSecondObjImpl

foreign import getFirstObjSrc :: forall s e. Eff (oe :: ObjEff s | e) FirstObjSrc
foreign import getSecondObjSrc :: forall s e. Eff (oe :: ObjEff s | e) SecondObjSrc

所以,我对这段代码有一些疑问:

  1. 这个实现正确吗?
  2. ObjEff效果需要幻影类型吗s
  3. 如果有(或没有),那么我想了解原因(我已经阅读了https://wiki.haskell.org/Phantom_type和其他一些的解释,我认为我了解基础知识,但效果让我有点困惑)。

更新

假设上面的代码是某种虚构的浏览器(或 NodeJS)API,因此无法以某种方式对其进行更改。

4

1 回答 1

0

此问题基于该语言的较旧且不兼容的版本,而不是当前版本。Eff并且效果行已被删除,取而代之的是Effect(基本上Eff没有效果行)。我猜*已经被替换Type并被!删除(当我开始使用 PureScript 时这些符号不存在)。

用于对象的表示法有点令人困惑,因为它既不是 JavaScript 也不是我熟悉的任何其他标准表示法。我的解释是,例如,

MainObj {
  someProp: false
  toggleSomeProp: function () {
    if (this.someProp)
      this.someProp = false
    else
      this.someProp = true
  }
  ...
}

意味着这个(在 JavaScript 中)

function MainObj() {
}
MainObj.prototype.someProp = false;
MainObj.prototype.toggleSomeProp = function () {
  if (this.someProp)
    this.someProp = false
  else
    this.someProp = true
}
// ...

在这种情况下,PureScript 中对此的可能定义是:

foreign import data MainObj ∷ Type

foreign import someProp ∷ MainObj → Effect Boolean

foreign import toggleSomeProp ∷ MainObj → Effect Unit

实现文件将是:

exports.someProp = function (mainObj) {
  return function () {
    return mainObj.someProp;
  };
};

exports.toggleSomeProp = function (mainObj) {
  return function () {
    return mainObj.toggleSomeProp();
  };
}

或者为了更好的内联和更容易的实现,这个:

foreign import data MainObj ∷ Type

foreign import someProp ∷ EffectFn1 MainObj Boolean

foreign import toggleSomeProp ∷ EffectFn1 MainObj Unit

实施将是:

exports.someProp = function (mainObj) {
  return mainObj.someProp;
};

exports.toggleSomeProp = function (mainObj) {
  return mainObj.toggleSomeProp();
}

有多种方法可以完成(并且已经完成),但这是我几乎完全使用的方法,因为它直截了当、显而易见且适应性强。

someProp必须导入有效,因为给定相同的对象它可以返回不同的结果。toggleSomeProp必须以有效的方式导入,因为它以可观察的方式(通过someProp)改变状态。

于 2019-04-05T00:57:55.463 回答