可能的目標是為Haskell中新定義的資料型別創建一個新的Semigroup型別實體(對于那些知道Will Kurt的"Get programming with Haskell "一書的人來說,我可以把你帶到第428頁,即頂點專案5的結尾,包括練習擴展)。
有一個新定義的資料型別:
data HINQ m a b = HINQ (m a -> m b) (m a) (m a -> m a)。
| HINQ_ (m a -> m b) (m a)
這個資料型別指定了類似SQL的查詢,其中m定義了背景關系(Monad或Alternative),(m a -> m b)是一個函式,其目標與SQL函式SELECT相似,即定義了想要的屬性種類。(m a)是一個 "表",它適用于前面的函式(類似于SQL的table_name),最后(m a -> m a)過濾出我們正在尋求的屬性(類似于SQL的WHERE)。
我的目標是讓這個資料型別成為一個半群的實體(最終成為一個單體)。值得一提的是,所有需要的a、b等的Semigroup實體都是假定的。
instance (Semigroup a, Semigroup (m a), Semigroup b,. ...)=>。
Semigroup (HINQ m a b) where>
(<>) (HINQ func1 start1 test1)
(HINQ func2 start2 test2) =
因此,它的粗略想法(在背景上看得更清楚)是使它有可能將幾個不同的資料庫查詢組成一個單一的查詢,但我想不出一個主意,如何將兩個不同的函式型別(m a -> m b)合并成一個,同時將兩個表(m a)合并。第一個想法是把它們合并成串列,但后來型別簽名發生了變化,我還沒有找到解決這個問題的方法。
uj5u.com熱心網友回復:
我認為你不想要一個Semigroup。組成所有對的查詢是沒有意義的--只有那些一個的輸出型別與另一個的輸入型別合理地匹配的查詢!我們有一個概念,就是 "Semigroup"。幸運的是,我們有一個與Semigroup的 "型別化 "變體相對應的概念(實際上是一個型別化的Monoid,但足夠接近)。Category.
此外,我認為將查詢與你所查詢的表聯系起來是一個設計錯誤。它們在概念上是獨立的概念;事實上,當組成兩個查詢時,你仍然只有一個表,而不是兩個。所以:
data HINQ m a b = HINQ (m a -> m b) (m a -> m a)
instance Category (HINQ m) where
id = HINQ id id
HINQ slct whr . HINQ slct' whr' = HINQ (slct . whr . slct') whr' 。
身份法則相當清楚,但左右WHERE子句的使用不對稱,看起來有點可疑,所以我們應該仔細檢查關聯性法則:
(HINQ s0 w0 。HINQ s1 w1) . HINQ s2 w2
= HINQ (s0 . w0 . s1) w1 . HINQ s2 w2
= HINQ (s0 . w0 . s1 . w1 . s2) w2.
= HINQ s0 w0 . HINQ (s1 . w1 . s2) w2
= HINQ s0 w0 . (HINQ s1 w1 . HINQ s2 w2)
看起來不錯!
編輯
呃,嗯......也許x .id = x定律畢竟不是那么清楚。Yikes! 這可能是無法解決的,除非你只考慮到所含函式的組成的平等性,在這種情況下,為什么不直接使用Category實體來處理函式呢?當然,你還有另一個選擇,就是不要求身份法則成立。這有點不尋常,但我想這在很大程度上取決于你的用例是否合理。
組合可能會更容易一些。
如果你更明確地表示你的過濾,例如,作為 a -> Bool 或 a -> m Bool 而不是 m a -> m a,組合可能會更容易。這讓你有更多的機會在你的(.)實作中結合這兩個過濾器,而不是像上面的實體那樣將其中一個過濾器滾動到選擇操作中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/316895.html
標籤:
