-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updates via “ix”, “at” do not seem to update secondary indices #15
Comments
I don't think this qualified as a bug. Consider how it would work in a traditional database, you would either have one field for the text and one field for the length and update manually, or you would just have a single field and calculate the length. You can do "with (\Foo k -> length k) (<=) 3" and it would work fine. |
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Foo where
import Control.Applicative
import Control.Lens
import Data.Table
data Foo = Foo { _k :: String, _v :: String }
deriving (Eq, Ord, Show, Read)
makeLenses ''Foo
instance Tabular Foo where
type PKT Foo = String
data Key k Foo a where
FooK :: Key Primary Foo String
FooV :: Key Supplemental Foo String
data Tab Foo i = FooTab (i Primary String)
(i Supplemental String)
fetch FooK = _k
fetch FooV = _v
primary = FooK
primarily FooK r = r
mkTab f = FooTab <$> f FooK <*> f FooV
forTab (FooTab a b) f = FooTab <$> f FooK a <*> f FooV b
ixTab (FooTab a _) FooK = a
ixTab (FooTab _ b) FooV = b
tableA, tableB, tableC, tableD, tableE, tableF, tableG, tableH :: Table Foo
tableA = fromList [Foo "a" "A", Foo "b" "hello"]
-- fromList [Foo {_k = "a", _v = "A"},Foo {_k = "b", _v = "hello"}]
tableB = tableA & ix "a" . v %~ take 8 . cycle
& ix "b" . v %~ take 8 . cycle . take 2
-- fromList [Foo {_k = "a", _v = "AAAAAAAA"},Foo {_k = "b", _v = "hehehehe"}]
tableC = tableB ^. with FooV (/=) ""
-- fromList [Foo {_k = "a", _v = "A"},Foo {_k = "b", _v = "hello"}]
tableD = tableB ^. with _v (/=) ""
-- fromList [Foo {_k = "a", _v = "AAAAAAAA"},Foo {_k = "b", _v = "hehehehe"}]
tableE = tableB ^. with FooV (==) "A"
-- fromList [Foo {_k = "a", _v = "A"}]
tableF = tableB ^. with _v (==) "A"
-- fromList []
tableG = tableB ^. with FooV (==) "AAAAAAAA"
-- fromList []
tableH = tableB ^. with _v (==) "AAAAAAAA"
-- fromList [Foo {_k = "a", _v = "AAAAAAAA"}] |
That looks like a bug to me! |
The issue is that setting with "primaryMap" doesn't update any of the copies of the table outside the map being modified, which breaks an invariant on Table. Luckily primaryMap is not exported, and is only used to set in the definition of ix and at. Because in each of these we know that only one record is being modified, it would be more efficient, I believe, to readjust the table in ix and at than changing primaryMap, where concievably the entire Map could be changed. I am working on a patch fixing this. |
Cool, thanks! I haven't had time for this, but I'd love to see this un-deprecated on hackage. |
I've worked on this some more, and I have come to an unfortunate conclusion: Table t has no valid Ix or At instance that preserves the invariant whose breakage lead to this issue. Consider
However, This breaks the Traversal laws, and there is a similar story for At. This prevents us with three options, as far as I can tell:
None of these options are particularly satisfying. Anyone have any better ideas? |
The instances in this package are actually expected to violate the laws around fusion. The very reason this package was put together was to explore what would happen if we built a library that just "operationally" used The illegal instances you mention are the intended behavior, not the current "quasi-legal" ones, which seem to have arisen by accident. |
tables 0.3.1
The text was updated successfully, but these errors were encountered: