So, here is my clumsy code implementing chained HashTable in Haskell.
{-# LANGUAGE FlexibleInstances #-}
import Data.Array(Array(..), array, bounds, elems, (//), (!))
import Data.List(foldl')
import Data.Char
import Control.Monad.State
class HashTranform a where
hashPrepare :: a -> Integer
instance HashTranform Integer where
hashPrepare = id
instance HashTranform String where
hashPrepare cs = fromIntegral (foldl' (flip ((+) . ord)) 0 cs)
divHashForSize :: (HashTranform a) => Integer -> a -> Integer
divHashForSize sz k = 1 + (hashPrepare k) `mod` sz
type Chain k v = [(k, v)]
chainWith :: (Eq k) => Chain k v -> (k, v) -> Chain k v
chainWith cs p#(k, v) = if (null after) then p:cs else before ++ p:(tail after)
where (before, after) = break ((== k) . fst) cs
chainWithout :: (Eq k) => Chain k v -> k -> Chain k v
chainWithout cs k = filter ((/= k) . fst) cs
data Hash k v = Hash {
hashFunc :: (k -> Integer)
, chainTable :: Array Integer (Chain k v)
}
--type HState k v = State (Hash k v)
instance (Show k, Show v) => Show (Hash k v) where
show = show . concat . elems . chainTable
type HashFuncForSize k = Integer -> k -> Integer
createHash :: HashFuncForSize k -> Integer -> Hash k v
createHash hs sz = Hash (hs sz) (array (1, sz) [(i, []) | i <- [1..sz]])
withSlot :: Hash k v -> k -> (Chain k v -> Chain k v) -> Hash k v
withSlot h k op
| rows < hashed = h
| otherwise = Hash hf (ht // [(hashed, op (ht!hashed))])
where hf = hashFunc h
ht = chainTable h
rows = snd (bounds ht)
hashed = hf k
insert' :: (Eq k) => Hash k v -> (k, v) -> Hash k v
insert' h p#(k, v) = withSlot h k (flip chainWith p)
delete' :: (Eq k) => Hash k v -> k -> Hash k v
delete' h k = withSlot h k (flip chainWithout k)
insert :: (Eq k) => Hash k v -> Chain k v -> Hash k v
insert src pairs = foldl' insert' src pairs
delete :: (Eq k) => Hash k v -> [k] -> Hash k v
delete src keys = foldl' delete' src keys
search :: (Eq k) => k -> Hash k v -> Maybe v
search k h
| rows < hashed = Nothing
| otherwise = k `lookup` (ht!hashed)
where hf = hashFunc h
ht = chainTable h
rows = snd (bounds ht)
hashed = hf k
The problem is I don't want to have to code like this:
new = intHash `insert` [(1112, "uygfd"), (211, "catdied")]
new' = new `delete` [(1112, "uygfd")]
I believe it's modified with State Monad somehow, but having read online tutorials I couldn't quite grasp how exactly it's done.
So could you show me how to implement at least insert, delete, search or any one of them to give exposition.
At the end of the day your "state" will be a Hash k v. Let's break the interface functions into two groups. First are "state dependent" functions like search k which has a type like Hash k v -> _ (where _ just means "something"). Second are the "state updating" functions like flip insert (k, v) and flip delete ks which have types like Hash k v -> Hash k v.
As you've noted, you can already simulate "state" by manually passing around the Hash k v argument. The State monad is nothing more than type magic to make that easier.
If you look at Control.Monad.State you'll see modify :: (s -> s) -> State s () and gets :: (s -> a) -> State s a. These functions transform your "state updating" and "state dependent" functions into "State monad actions". So now we can write a combined State monad action like so
deleteIf :: (v -> Bool) -> k -> State (Hash k v) ()
deleteIf predicate k = do
v <- gets $ search k
case fmap predicate v of
Nothing -> return ()
Just False -> return ()
Just True -> modify $ flip delete [k]
and then we can sequence together larger computations
computation = deleteIf (>0) 'a' >> deleteIf (>0) 'b'
and then execute them by "running" the State monad
runState computation (createHash f 100)
Related
I'm looking for a Haskell function that combines two Maps of different types. I.e. something like
mergeWith :: (a -> b -> c) -> Map k a -> Map k b -> Map k c
I want it to behave like an inner join in SQL.
unionWith doesn't cut it since it requires both Maps to have values of the same type.
Is there such a function? If not, what's the most efficient way to implement it?
Does intersectionWith not fit the bill?
This was the best that I could do myself
import qualified Data.Map.Strict as M
mergeWith :: (Ord k) => (a -> b -> c) -> M.Map k a -> M.Map k b -> M.Map k c
mergeWith f m1 m2 = M.fromList $ g (M.toList m1) (M.toList m2)
where
g [] _ = []
g _ [] = []
g m1'#((k1, v1):_) m2'#((k2, v2):_)
| k1 < k2 = g (tail m1') m2'
| k1 > k2 = g m1' (tail m2')
| otherwise = (k1, f v1 v2) : g (tail m1') (tail m2')
It sholud have O(n) complexity where n is the size of the bigger Map
Consider the following type constructor:
newtype Mapnad k v = Mapnad { runMapnad :: Map [k] v }
Since Ord k => Ord [k] (lexicographical order), we can reuse the functor instance for maps for this type in an obvious way:
deriving instance Ord k => Functor (Mapnad k)
Furthermore, it seems as though Ord k => Monad (Mapnad k), according to the following scheme:
-- For readability
type (×) = (,)
infixr ×
toList' :: Ord k => Mapnad k v -> [[k] × v]
fromList' :: Ord k => [[k] × v] -> Mapnad k v
return' :: Ord k => a -> Mapnad k a
return' = fromList' . return . return
join' :: Ord k => Mapnad k (Mapnad k v) -> Mapnad k v
join' =
fmap toList' -- Mapnad k [[k] × v]
>>> toList' -- [[k] × [[k] × v]]
>>> (=<<) sequenceA -- [[k] × [k] × v]
>>> fmap join -- [[k] × v]
>>> fromList' -- Mapnad k v
-- Note: we are using the writer monad for tuples above
instance Ord k => Applicative (Mapnad k)
where
pure = return
(<*>) = ap
instance Ord k => Monad (Mapnad k)
where
return = return'
ma >>= amb = join' $ fmap amb ma
Is this a legal monad instance? QuickCheck seems to suggest so, but it'd be good to know for sure one way or the other.
Bonus question: Assuming this is indeed a monad, are there any monoids k besides the free [a] monoid for which Map k is a monad? There are certainly counterexamples: i.e. monoids k for which Map k is not a monad. For instance, with the same monad instance for Map (Sum Int), QuickCheck finds a counterexample to the associativity law.
-- m >>= (\x -> k x >>= h) == m >>= k >>= h
m :: { 0 -> 0; 3 -> 7 }
k :: \x -> if (odd x) then { -3 -> 1 } else { 0 -> 0 }
h :: \x -> if (odd x) then { } else { 0 -> 0 }
It is not a monad. We can adapt your counterexample for Sum; the key property is that 3 <> -3 = 0 = 0 <> 0, which introduces a choice point for the value that 0 maps to in m >>= k. We can choose, e.g., "" <> "a" = "a" <> "" to set up the same choice. So:
m = { "" -> 0; "a" -> 7 }
k x = if odd x then { "" -> 1 } else { "a" -> 0 }
h x = if odd x then { } else { "" -> 0 }
Then I observe:
m >>= k >>= h = { }
m >>= (\x -> k x >>= h) = { "a" -> 0 }
Every non-trivial monoid has such choice points. The associativity property of monoids says:
a <> (b <> c) = (a <> b) <> c
So you are in trouble if there are any a and b for which a /= a <> b.
(It is a monad if you choose the trivial monoid: specifically, it is (monad-isomorphic to) Maybe.)
I have the following structure:
y = [
fromList([("c", 1 ::Int)]),
fromList([("c", 5)]),
fromList([("d", 20)])
]
I can use this to update every "c":
y & mapped . at "c" . mapped %~ (+ 1)
-- [fromList [("c",2)], fromList [("c",6)], fromList [("d",20)]]
So the third entry is basically just ignored. But I want is for the operation to fail.
Only update, iff all the maps contain the key "c".
So I want:
y & mysteryOp
-- [fromList [("c",1)], fromList [("c",5)], fromList [("d",20)]]
-- fail because third entry does not contain "c" as key
I think I know which functions to use here:
over
-- I want to map the content of the list
mapped
-- map over the structure and transform to [(Maybe Int)]
traverse
-- I need to apply the operation, which will avoid
at "c"
-- I need to index into the key "c"
I just don't know how to combine them
Here's a couple of alternative approaches seeing as you like lenses;
Using laziness to delay deciding whether or not to make the changes,
f y = res
where (All c, res) = y
& each %%~ (at "c" %%~ (Wrapped . is _Just &&& fmap (applyWhen c succ)))
Or deciding upfront whether to make the changes,
f' y = under (anon y $ anyOf each (nullOf $ ix "c")) (mapped . mapped . ix "c" +~ 1) y
I don't see a way to write it as a simple composition of lens combinators, but this is a traversal that you can write from scratch. It should either traverse all values of "c" keys if every map contains such a key or else traverse no values.
We can start with a helper function to "maybe" update a map with a new key value, failing in the Maybe monad if the key doesn't exist. For reasons that will become apparent, we want to allow the update to occur in an arbitrary functor. That is, we want a function:
maybeUpdate :: (Functor f, Ord k) => k -> (v -> f v) -> Map k v -> Maybe (f (Map k v))
Is that signature clear? We check for the key k. If the key is found, we'll return Just an updated map with the key's corresponding value v updated in the f functor. Otherwise, if the key is not found, we return Nothing. We can write this pretty clearly in monad notation, though we need the ApplicativeDo extension if we only want to use Functor f constraint:
maybeUpdate :: (Functor f, Ord k) => k -> (v -> f v) -> Map k v -> Maybe (f (Map k v))
maybeUpdate k f m = do -- in Maybe monad
v <- m ^. at k
return $ do -- in "f" functor
a <- f v
return $ m & at k .~ Just a
Alternatively, these "monadic actions" are really just functor actions, so this definition can be used:
maybeUpdate' k f m =
m ^. at k <&> \v -> f v <&> \a -> m & at k .~ Just a
That's the hard part. Now, the traversal is pretty straightforward. We start with the signature:
traverseAll :: (Ord k) => k -> Traversal' [Map k v] v
traverseAll k f maps =
The idea is that this traversal starts by traversing the list of maps over the Maybe applicative using the maybeUpdate helper:
traverse (maybeUpdate k f) maps :: Maybe [f (Map k v)]
If this traversal succeeds (returns Just a list), then all keys were found, and we can sequence the f applicative actions:
sequenceA <$> traverse (maybeUpdate k f) maps :: Maybe (f [Map k v])
Now, we just use maybe to return the original list if the traversal fails:
traverseAll k f maps = maybe (pure maps) id (sequenceA <$> traverse (maybeUpdate k f) maps)
Now, with:
y :: [Map String Int]
y = [
fromList([("c", 1 ::Int)]),
fromList([("c", 5)]),
fromList([("d", 20)])
]
y2 :: [Map String Int]
y2 = [
fromList([("c", 1 ::Int)]),
fromList([("c", 5)]),
fromList([("d", 20),("c",6)])
]
we have:
> y & traverseAll "c" %~ (1000*)
[fromList [("c",1)],fromList [("c",5)],fromList [("d",20)]]
> y2 & traverseAll "c" %~ (1000*)
[fromList [("c",1000)],fromList [("c",5000)],fromList [("c",6000),("d",20)]]
Full disclosure: I was not able to construct traverseAll like that from scratch. I started with the much stupider "traversal" in the implicit identity applicative:
traverseAllC' :: (Int -> Int) -> [Map String Int] -> [Map String Int]
traverseAllC' f xall = maybe xall id (go xall)
where go :: [Map String Int] -> Maybe [Map String Int]
go (x:xs) = case x !? "c" of
Just a -> (Map.insert "c" (f a) x:) <$> go xs
Nothing -> Nothing
go [] = Just []
and once I got that up and running, I simplified it, made the Identity explicit:
traverseAllC_ :: (Int -> Identity Int) -> [Map String Int] -> Identity [Map String Int]
and converted it to a general applicative.
Anyway, here's the code:
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RankNTypes #-}
import Data.Map (Map, fromList)
import Control.Lens
y :: [Map [Char] Int]
y = [
fromList([("c", 1 ::Int)]),
fromList([("c", 5)]),
fromList([("d", 20)])
]
y2 :: [Map [Char] Int]
y2 = [
fromList([("c", 1 ::Int)]),
fromList([("c", 5)]),
fromList([("d", 20),("c",6)])
]
traverseAll :: (Ord k) => k -> Traversal' [Map k v] v
traverseAll k f maps = maybe (pure maps) id (sequenceA <$> traverse (maybeUpdate k f) maps)
maybeUpdate :: (Functor f, Ord k) => k -> (v -> f v) -> Map k v -> Maybe (f (Map k v))
maybeUpdate k f m = do
v <- m ^. at k
return $ do
a <- f v
return $ m & at k .~ Just a
maybeUpdate' :: (Functor f, Ord k) => k -> (v -> f v) -> Map k v -> Maybe (f (Map k v))
maybeUpdate' k f m =
m ^. at k <&> \v -> f v <&> \a -> m & at k .~ Just a
main = do
print $ y & traverseAll "c" %~ (1000*)
print $ y2 & traverseAll "c" %~ (1000*)
Consider the following code snippet (from http://lpaste.net/180651):
{-# LANGUAGE ScopedTypeVariables #-}
class Natural n
newtype V n a = V [a]
dim :: Natural n => V n a -> Int
dim = undefined -- defined in my actual code
bad_fromList :: Natural n => [a] -> V n a
bad_fromList l = if length l == dim v then v else undefined -- this is line 11
where v = V l
good_fromList :: forall n a. Natural n => [a] -> V n a
good_fromList l = if length l == dim v then v else undefined
where v = V l :: V n a
GHCI gives the following error message:
test.hs:11:33: error:
• Could not deduce (Natural n0) arising from a use of ‘dim’
from the context: Natural n
bound by the type signature for:
bad_fromList :: Natural n => [a] -> V n a
at test.hs:10:1-41
The type variable ‘n0’ is ambiguous
• In the second argument of ‘(==)’, namely ‘dim v’
In the expression: length l == dim v
In the expression: if length l == dim v then v else undefined
Why can't GHCI deduce the type?
Or, in the following code, pure' and good_f compile, while bad_f gives a similar error message. Why?
pure' :: Natural n => a -> V n a
pure' x = v
where v = V $ replicate (dim v) x
bad_f :: Natural n => [a] -> (V n a, Int)
bad_f xs = (v, dim v)
where v = V xs
good_f :: Natural n => a -> (V n a, Int)
good_f x = (v, dim v)
where v = V $ replicate (dim v) x
As user2407038 suggested, enabling -XMonoLocalBinds makes the code work.
I can define the needed Lens' manually:
type Key = String
type Val = Int
type Foo = Map Key (Either Val Bool)
ll :: String -> Lens' Foo (Maybe Int)
ll k f m = f mv <&> \r -> case r of
Nothing -> maybe m (const (Map.delete k m)) mv
Just v' -> Map.insert k (Left v') m
where mv = Map.lookup k m >>= maybeLeft
maybeLeft (Left v') = Just v'
maybeLeft (Right _) = Nothing
And it works like:
x, y :: Foo
x = Map.empty
y = Map.fromList [("foo", Right True)]
>>> x ^. ll "foo"
Nothing
>>> x & ll "foo" ?~ 1
fromList [("foo",Left 1)]
>>> (x & ll "foo" ?~ 1) ^. ll "foo"
Just 1
>>> (x & ll "foo" ?~ 1) ^. ll "bar"
Nothing
>>> x & ll "foo" ?~ 1 & ll "foo" .~ Nothing
fromList []
>>> y ^. ll "foo"
Nothing
>>> y & ll "foo" ?~ 1
fromList [("foo",Left 1)]
>>> y & ll "foo" .~ Nothing
fromList [("foo",Right True)]
I verified that definition is lawful:
-- Orphan instance is ok-ish in this case :)
instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where
arbitrary = Map.fromList <$> arbitrary
-- 1) You get back what you put in:
lensLaw1 :: Foo -> Key -> Maybe Val -> Property
lensLaw1 s k v = view (ll k) (set (ll k) v s) === v
-- 2) Putting back what you got doesn't change anything:
lensLaw2 :: Foo -> Key -> Property
lensLaw2 s k = set (ll k) (view (ll k) s) s === s
-- 3) Setting twice is the same as setting once:
lensLaw3 :: Foo -> Key -> Maybe Val -> Maybe Val -> Property
lensLaw3 s k v v' = set (ll k) v' (set (ll k) v s) === set (ll k) v' s
So the question: can the ll be defined using at and _Left?
Maybe with some kind of prismToLens :: Prism' a b -> Lens' (Maybe a) (Maybe b), you can do at k . prismToLens _Left. Yet I'm not sure if prismToLens makes sense? Hoogle isn't that helpful with lens :(
EDIT seems that third law doesn't hold always. Easy to find counter-example if you change Key to be Bool. Yet in my application the Map is actually dependent, i.e. the sum branch depends on the key, so the Lens law should hold (if I access foo, I know it should be Left or not exist at all).
For now I go with:
prismToLens :: Prism' a b -> Lens' (Maybe a) (Maybe b)
prismToLens p = lens getter setter
where getter s = s >>= (^? p)
setter _ b = (p#) <$> b
so I can define ll like:
ll' :: Key -> Lens' Foo (Maybe Val)
ll' k = at k . prismToLens _Left
Controrary to the "lens" defined in the question, for this one 2nd law doesn't hold:
-- 2) Putting back what you got doesn't change anything:
-- Doesn't hold
-- >>> quickCheck $ lensLaw2' (Map.fromList [(True,Right False)]) True
-- fromList [] /= fromList [(True,Right False)]
lensLaw2' :: Foo -> Key -> Property
lensLaw2' s k = set (ll' k) (view (ll' k) s) s === s
But with original the third law didn't hold:
-- 3) Setting twice is the same as setting once:
-- Doesn't hold
-- >>> quickCheck $ lensLaw3 (Map.fromList [(False, Right False)]) False (Just 0) Nothing
-- fromList [] /= fromList [(True,Right False)]
lensLaw3 :: Foo -> Key -> Maybe Val -> Maybe Val -> Property
lensLaw3 s k v v' = set (ll k) v' (set (ll k) v s) === set (ll k) v' s
As said in the question as I have dependend map, this is ok. When accessing some key k, there shouldn't ever be Right value, if I expect there to be Left. Taking this into the account, using prismToLens is actually better. Still searching for a better name though.
After remembering non, I altered the answer to use:
prismToIso :: Prism' a b -> Iso' (Maybe a) (Maybe b)
prismToIso p = iso t f
where t a = a >>= (^? p)
f b = (p#) <$> b -- no unused param as in `prismToLens`!
Which resembles mapping. The law properties behaved the same as with prismToLens. This gives rise to the new questio: which one is better or worse, prismToIso or prismToLens. And why?
The full runnable example:
{-# LANGUAGE RankNTypes #-}
module Lens where
import Control.Applicative
import Control.Lens
import Data.Map as Map
import Test.QuickCheck
type Key = Bool
type Val = Int
type Foo = Map Key (Either Val Bool)
ll :: Key -> Lens' Foo (Maybe Val)
ll k f m = f mv <&> \r -> case r of
Nothing -> maybe m (const (Map.delete k m)) mv
Just v' -> Map.insert k (Left v') m
where mv = Map.lookup k m >>= maybeLeft
maybeLeft (Left v') = Just v'
maybeLeft (Right _) = Nothing
prismToLens :: Prism' a b -> Lens' (Maybe a) (Maybe b)
prismToLens p = lens getter setter
where getter s = s >>= (^? p)
setter _ b = (p#) <$> b
ll' :: Key -> Lens' Foo (Maybe Val)
ll' k = at k . prismToLens _Left
x, y :: Foo
x = Map.empty
y = Map.fromList [(True, Right True)]
{-
>>> x ^. ll "foo"
Nothing
>>> x & ll "foo" ?~ 1
fromList [("foo",Left 1)]
>>> (x & ll "foo" ?~ 1) ^. ll "foo"
Just 1
>>> (x & ll "foo" ?~ 1) ^. ll "bar"
Nothing
>>> x & ll "foo" ?~ 1 & ll "foo" .~ Nothing
fromList []
>>> y ^. ll "foo"
Nothing
>>> y & ll "foo" ?~ 1
fromList [("foo",Left 1)]
>>> y & ll "foo" .~ Nothing
fromList [("foo",Right True)]
-}
-- Orphan instance is ok-ish in this case :)
instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) where
arbitrary = Map.fromList <$> arbitrary
shrink = Prelude.map Map.fromList . shrink . Map.toList
-- 1) You get back what you put in:
lensLaw1 :: Foo -> Key -> Maybe Val -> Property
lensLaw1 s k v = view (ll k) (set (ll k) v s) === v
-- 2) Putting back what you got doesn't change anything:
lensLaw2 :: Foo -> Key -> Property
lensLaw2 s k = set (ll k) (view (ll k) s) s === s
-- 3) Setting twice is the same as setting once:
-- Doesn't hold
-- >>> quickCheck $ lensLaw3 (Map.fromList [(False, Right False)]) False (Just 0) Nothing
-- fromList [] /= fromList [(True,Right False)]
lensLaw3 :: Foo -> Key -> Maybe Val -> Maybe Val -> Property
lensLaw3 s k v v' = set (ll k) v' (set (ll k) v s) === set (ll k) v' s
-- Using prismToLens defined "lens"
-- 1) You get back what you put in:
lensLaw1' :: Foo -> Key -> Maybe Val -> Property
lensLaw1' s k v = view (ll' k) (set (ll' k) v s) === v
-- 2) Putting back what you got doesn't change anything:
-- Doesn't hold
-- >>> quickCheck $ lensLaw2' (Map.fromList [(True,Right False)]) True
-- fromList [] /= fromList [(True,Right False)]
lensLaw2' :: Foo -> Key -> Property
lensLaw2' s k = set (ll' k) (view (ll' k) s) s === s
-- 3) Setting twice is the same as setting once:
lensLaw3' :: Foo -> Key -> Maybe Val -> Maybe Val -> Property
lensLaw3' s k v v' = set (ll' k) v' (set (ll' k) v s) === set (ll' k) v' s