2016-07-19 25 views
0

在我的應用程序中,我想使用類似於關係數據庫索引的結構以類型安全的方式對對象集進行索引。例如,我希望索引基於年齡和名字一組用戶對象:我應該如何在Purescript中建立一個類型安全的索引?

import Data.Map as M 
import Data.Set as S 

type AgeNameIndex = M.Map Int (M.Map String (S.Set User)) 

此外,我想有效地完成操作,如在指標uniondifference,如:

let a = M.singleton 42 $ M.singleton "Bob" $ S.singleton $ User { ... } 
    b = M.singleton 42 $ M.singleton "Tim" $ S.singleton $ User { ... } 
    c = union a b -- contains both Bob and Tim 

我試圖模擬這種如下:

module Concelo.Index 
    (index 
    , union 
    , subtract 
    , lastValue 
    , subIndex) where 

import Prelude (($), (>>>), flip, Unit, unit, class Ord) 
import Control.Monad ((>>=)) 
import Data.Map as M 
import Data.Set as S 
import Data.Maybe (Maybe(Nothing, Just), fromMaybe) 
import Data.Tuple (Tuple(Tuple)) 
import Data.Foldable (foldl) 
import Data.Monoid (mempty) 

class Index index key value subindex where 
    isEmpty :: index -> Boolean 
    union :: index -> index -> index 
    subtract :: index -> index -> index 
    lastValue :: index -> Maybe value 
    subIndex :: key -> index -> subindex 

instance mapIndex :: (Index subindex subkey value subsubindex) => 
        Index (M.Map key subindex) key value subindex where 
    isEmpty = M.isEmpty 

    union small large = 
    foldl (m (Tuple k v) -> M.alter (combine v) k m) large (M.toList small) 
    where 
     combine v = case _ of 
     Just v' -> Just $ union v v' 
     Nothing -> Just v 

    subtract small large = 
    foldl (m (Tuple k v) -> M.alter (minus v) k m) large (M.toList small) 
    where 
     minus v = (_ >>= v' -> 
        let subindex = subtract v v' in 
        if isEmpty subindex then Nothing else Just subindex) 

    lastValue m = M.findMax m >>= (_.value >>> lastValue) 

    subIndex k m = fromMaybe mempty $ M.lookup k m 

instance setIndex :: (Ord value) => Index (S.Set value) Unit value Unit where 
    isEmpty = S.isEmpty 

    union = S.union 

    subtract = flip S.difference 

    lastValue s = Nothing -- todo: S.findMax 

    subIndex _ _ = unit 

index f = foldl (acc v -> union (f v) acc) mempty 

然而,Purescript編譯器不一樣的是:

Compiling Concelo.Index 
Error found: 
in module Concelo.Index 
at /home/dicej/p/pssync/src/Concelo/Index.purs line 24, column 1 - line 44, column 49 

    No type class instance was found for 

    Concelo.Index.Index subindex0 
         t1  
         t2  
         t3  

    The instance head contains unknown type variables. Consider adding a type annotation. 

in value declaration mapIndex 

where subindex0 is a rigid type variable 
     t1 is an unknown type 
     t2 is an unknown type 
     t3 is an unknown type 

See https://github.com/purescript/purescript/wiki/Error-Code-NoInstanceFound for more information, 
or to contribute content related to this error. 

我這個消息的理解是,我還沒有正確地指出,在mapIndex實例映射值本身Index情況下,但我不知道如何解決這個問題。我可以在哪裏添加一個類型註釋來進行編譯?或者我甚至在正確的軌道上給予我想要做的事情?

回答

1

這幾乎可以肯定是因爲PureScript目前缺乏使這種信息無法推測的函數依賴關係(或類型族)。這裏有一個問題的寫作:https://github.com/purescript/purescript/issues/1580 - 這是我們想要支持的東西。

有大約一案非常相似,這今天的討論,因爲它發生:https://github.com/purescript/purescript/issues/2235

從本質上講,這裏的問題是,這個類的功能不使用所有類型的變量,這意味着沒有將信息傳播到查找合適實例的約束的方式。

我並沒有真正的建議如何在事情發生之後如何做到這一點,除了避免班級和考慮特定類型的情況。

+0

謝謝,加里。我獨立地遇到#1580,並想知道它是否可能與我的問題有關。 #1280也似乎相關。同時,我會看看我是否可以在沒有班級的情況下進行管理。 –

+0

現在有什麼想法可以解決我的問題,現在PureScript具有函數依賴關係? –

相關問題