我試圖在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