我试图在Haskell中编写一个数据处理模块,它接受与不同模式有关的changesets
,并通过一系列可选择地根据数据执行操作的规则传递这些模块。 (这主要是一个学术活动,以更好地了解了Haskell)模式与Haskell函数中的类型实例匹配
为了更好地解释我在做什么,这里是斯卡拉
// We have an open type allowing us to define arbitrary 'Schemas'
// in other packages.
trait Schema[T]
// Represents a changeset in response to user action - i.e. inserting some records into a database.
sealed trait Changeset[T]
case class Insert[T](schema:Schema[T], records:Seq[T]) extends Changeset[T]
case class Update[T](schema:Schema[T], records:Seq[T]) extends Changeset[T]
case class Delete[T](schema:Schema[T], records:Seq[T]) extends Changeset[T]
// Define a 'contacts' module containing a custom schema.
package contacts {
object Contacts extends Schema[Contact]
case class Contact(firstName:String, lastName:String)
}
// And an 'accounts' module
package accounts {
object Accounts extends Schema[Account]
case class Account(name:String)
}
// We now define an arbitrary number of rules that each
// changeset will be checked against
trait Rule {
def process(changeset: Changeset[_]):Unit
}
// As a contrived example, this rule keeps track of the
// number of contacts on an account
object UpdateContactCount extends Rule {
// To keep it simple let's pretend we're doing IO directly here
def process(changeset: Changeset[_]):Unit = changeset match {
// Type inference correctly infers the type of `xs` here.
case Insert(Contacts, xs) => ??? // Increment the count
case Delete(Contacts, xs) => ??? // Decrement the count
case Insert(Accounts, xs) => ??? // Initialize to zero
case _ =>() // Don't worry about other cases
}
}
val rules = [UpdateContactCount, AnotherRule, SomethingElse]
工作的例子。重要的是,这两个“纲要”和'规则'是可以扩展的,这部分特别是在我尝试在Haskell中做这件事情的时候会抛出一些曲线球。
我至今在Haskell是
{-# LANGUAGE GADTs #-}
-- In this example, Schema is not open for extension.
-- I'd like it to be
data Schema t where
Accounts :: Schema Account
Contacts :: Schema Contact
data Account = Account { name :: String } deriving Show
data Contact = Contact { firstName :: String, lastName :: String } deriving Show
data Changeset t = Insert (Schema t) [t]
| Update (Schema t) [t]
| Delete (Schema t) [t]
-- Whenever a contact is inserted or deleted, update the counter
-- on the account. (Or, for new accounts, set to zero)
-- For simplicity let's pretend we're doing IO directly here.
updateContactCount :: Changeset t -> IO()
updateContactCount (Insert Contacts contacts) = ???
updateContactCount (Delete Contacts contacts) = ???
updateContactCount (Insert Accounts accounts) = ???
updateContactCount other = return()
此示例工作正常 - 但我想在这这样展开两Schema
可以是开放式(即我不知道所有提前的可能性),同时也为规则做同样的事情。即我不知道updateContactCount
函数时间头,我简单地通过了一个[Rule]
类型的列表。即类似的东西。
type Rule = Changeset -> IO()
rules = [rule1, rule2, rule3]
我第一次尝试是通过创建一个Schema
类型类来代替,但哈斯克尔仍然坚持对功能锁定到一个单一的类型。数据种类似乎具有相同的限制。
由此,我确实有两个具体问题。
是否有可能创建一个功能,可以模式匹配打开类型,就像我们可以在斯卡拉?
在Haskell中有没有更优雅的惯用方式处理上述场景?
你的意思是'rules :: [Rule]',而不是'='? – 2015-02-08 09:54:45
没有。我的意思是'规则= [规则1,规则2,规则3]'。我看到我的错字 - 将会修改。 – 2015-02-08 11:12:53