如何处理某些新类型分组

时间:2018-07-01 06:55:11

标签: purescript

我正在努力使以下各项起作用,但似乎无法正确解决。我希望像这样的东西能起作用:

newtype Skill = Skill { name :: String, other :: Int }
newtype Feature = Feature { name :: String, something :: Boolean }
newtype Special = Special { name :: String, different :: String }

type Namable = forall r. { name :: String | r }

changeName :: forall m. String -> m Namable -> m Namable
changeName newName (ctor namable) = 
    ctor $ namable { name = newName }

错误看起来像:

Error 1 of 1
  Unable to parse module:
  unexpected "namable"
  expecting @, ::, operator or )

基本上,我想向一组newtype添加功能。这并不总是完整的集合,也不总是一个以上的集合,但是我想写我定义的类型的实际功能“无知”。如果将来我决定添加一个newtype Statistic,我希望它“正常工作”。

为了改善这个问题,我想知道我要寻找的签名类型是否有名称?

f :: forall m a. (a -> a) -> m a -> m a

似乎不太通用的Functor定义。

1 个答案:

答案 0 :(得分:1)

好像我需要的是Newtype类型类:

newtype Skill = Skill { name :: String, other :: Int }
derive instance newtypeSkill :: Newtype Skill _
newtype Feature = Feature { name :: String, something :: Boolean }
derive instance newtypeFeature :: Newtype Feature _
newtype Special = Special { name :: String, different :: String }
derive instance newtypeSpecial :: Newtype Special _

type Namable = forall r. { name :: String | r }

changeModel ::forall p m. Newtype m p => (p -> p) -> m -> m
changeModel f m = over wrap f m

changeName :: forall m. Newtype m Namable => String -> m -> m
changeName newName m = changeModel (\x -> x { name = newName }) m

fishing :: Skill
fishing = Skill { name : "Fishing", other : 2 }

skating = changeName "Skating" fishing

changeModel函数现在在Newtype类型上是完全通用的。 changeName现在和函数应用程序一样简单。

详细信息:

因为我使用的是Newtype(另请参阅this info,所以我免费获得overwrap之类的东西。

over函数很难理解,因为示例以无点样式编写。

wrap函数返回类型构造函数。

lambda函数是“您要对新类型的数据执行的操作”。

最后的m是您要传递的实际值。这是被解包并传递给lambda的值。