what would be the best way of filtering the following nested map, keeping the nested map structure. In my example Alice and Bob can be duplicated, e.g. the same employee can be working in several different plants at a time.
(def universe
{:customer1
{:plant1
{ "Alice" {:age 35 :sex "F"}
"Bob" {:age 25 :sex "M"}}
:plant2 {}}
:customer2 {}
})
I would like to for example filter by age >30 and return the same map structure. Ideally this would work for any nested map depth, filtering on the innermost level. Expected result:
(def universe
{:customer1
{:plant1
{ "Alice" {:age 35 :sex "F"}
}
:plant2 {}}
:customer2 {}
})
I've looked at clojure filter nested map to return keys based on inner map values but it doesn't look to be solving my problem. Thank you,
It is very similar to one of previous questions:
(use '[com.rpl.specter])
(let [input {:customer1
{:plant1
{"Alice" {:age 35 :sex "F"}
"Bob" {:age 25 :sex "M"}}
:plant2 {}}
:customer2 {}}
desired-output {:customer1
{:plant1 {"Alice" {:age 35 :sex "F"}}
:plant2 {}}
:customer2 {}}
RECUR-MAP (recursive-path [] p (cond-path map? (continue-then-stay [MAP-VALS p])))]
(clojure.test/is (= (setval [RECUR-MAP (pred :age) #(> 30 (:age %))] NONE input)
desired-output)))
Your data is a bit unusual in that one would normally expect :customer1, :customer2 etc to be different entries in a vector. For semi-structured data like this, I would consider postwalk:
(ns tst.demo.core
(:use tupelo.core demo.core tupelo.test)
(:require
[clojure.walk :as walk] ))
(def universe
{:customer1
{:plant1
{"Alice" {:age 35 :sex "F"}
"Bob" {:age 25 :sex "M"}}
:plant2 {}}
:customer2 {}})
(def age-of-wisdom 30)
(defn wisdom-only
[form]
(let [filter-entry? (when (map-entry? form)
(let [[-name- details] form
age (:age details)] ; => nil if missing
(and age ; ensure not nil
(< age age-of-wisdom))))]
(if filter-entry?
{}
form)))
(walk/postwalk wisdom-only universe) =>
{:customer1
{:plant1
{"Alice" {:age 35, :sex "F"}}
:plant2 {}}
:customer2 {}}
Thanks to #akond for the answer, reading the code made me think of a non specter solution. Still, slightly surprised there's no easy way to apply filter in this use case.
(defn recursive-filter [pred k m]
(letfn [(pair-filter [pair] (if (pred (k (second pair))) pair nil))]
(into {}
(for [a m]
(if (empty? (second a))
[(first a) {}]
(if (contains? (second a) k)
(pair-filter a)
[(first a) (recursive-filter pred k (second a))]))))))
I am currently trying to erase all unused indices from my Idris
program - in one case however, the Idris compiler sees indices
as reachable. I tried to replicate the behaviour in the following
minimal example:
module Main
%access public export
-- CUSTOM VECTOR TYPES
data VectA : Nat -> Type -> Type where
VNilA : VectA Z a
VConsA : a -> VectA len a -> VectA (S len) a
data VectB : Nat -> Type -> Type where
VNilB : VectB Z a
VConsB : a -> VectB len a -> VectB (S len) a
-- THE FOLLOWING FUNCTIONS ARE USED TO CREATE A
-- CUSTOM VECTOR WHERE THE SIZE IS UNKNOWN
fromList : (l : List a) -> VectA (length l) a
fromList [] = VNilA
fromList (x::xs) = VConsA x (fromList xs)
createList : String -> List Int
createList "42" = [42, 42, 42]
createList _ = [1, 2, 3, 4]
-- SOME NESTED TRANSFORMATION FUNCTIONS ON VECT
transformVectA : VectA n a -> Maybe (VectB n a)
transformVectA VNilA = Just VNilB
transformVectA (VConsA v vs) =
case transformVectA vs of
Just vs' => Just $ VConsB v vs'
Nothing => Nothing
transformVectB : VectA m a -> VectB n a -> Maybe (VectB n a)
transformVectB VNilA ws = Just ws
transformVectB (VConsA v vs) ws = transformVectB vs ws
transformVect : VectA n a -> VectA m a -> Maybe (VectB n a)
transformVect VNilA VNilB = Nothing
transformVect VNilA VNilA = Nothing
transformVect vs VNilA = Nothing
transformVect (VConsA v vs) xs =
case transformVectA (VConsA v vs) of
Nothing => Nothing
Just vs' => transformVectB xs vs'
main : IO ()
main = do
(testArg :: _) <- getArgs
ls <- pure $ createList testArg
va <- pure $ fromList ls
vb <- pure $ transformVect va va
putStrLn "OK"
When this is compiled by running:
idris Erasure.idr -o Erasure --warnreach
...the following warnings are shown:
Main.transformVect: inaccessible arguments reachable:
n (no more information available)
m (no more information available)
I also have trouble reading the dumpcases when
compiling with the additional option:
--dumpcases cases.txt
Why do these warnings appear ?
Is there any information available about how Idris is handling
erasure besides the Chapter 'Erasure By Usage Analysis' in the
Tutorial ?
I try to create a program in haskell and Qt which displays in a graph some points got from an haskell function.
here is a working sample, but the point is in the return function and its parameters, not the rest of the code!
main :: IO ()
main = do
clazz <- newClass [
defMethod' "factorial" (\_ t𐌴xt𐌴 ->
let n = read $ T.unpack t𐌴xt𐌴 :: Integer
in return . T.pack . show $ product [1..n] :: IO Text)]
ctx <- newObject clazz ()
runEngineLoop defaultEngineConfig {
initialDocument = fileDocument "exemple4.qml",
contextObject = Just $ anyObjRef ctx}
here is my code:
main :: IO ()
main = do
clazz <- newClass [
defMethod' "init_tableau" (\_ ->
return $ map (^2) [0..20])]
ctx <- newObject clazz ()
runEngineLoop defaultEngineConfig {
initialDocument = fileDocument "exemple4.qml",
contextObject = Just $ anyObjRef ctx}
it should only return the 21 first occurences of i^2, beginning from 0.
and here are all the errors:
Build FAILED
/home/lowley/Documents/haskell/Qt/lancer-qml4.hs: line 10, column 9:
No instance for (MethodSuffix (m0 [b0]))
arising from a use of defMethod'
The type variables `m0', `b0' are ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance (Marshal a, CanGetFrom a ~ Yes, MethodSuffix b) =>
MethodSuffix (a -> b)
-- Defined in `Graphics.QML.Objects'
instance (Marshal a, CanReturnTo a ~ Yes) => MethodSuffix (IO a)
-- Defined in `Graphics.QML.Objects'
Possible fix:
add an instance declaration for (MethodSuffix (m0 [b0]))
In the expression:
defMethod' "init_tableau" (\ _ -> return $ map (^ 2) [0 .. 20])
In the first argument of `newClass', namely
`[defMethod' "init_tableau" (\ _ -> return $ map (^ 2) [0 .. 20])]'
In a stmt of a 'do' block:
clazz <- newClass
[defMethod' "init_tableau" (\ _ -> return $ map (^ 2) [0 .. 20])]
/home/lowley/Documents/haskell/Qt/lancer-qml4.hs: line 11, column 13:
No instance for (Monad m0) arising from a use of `return'
The type variable `m0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Monad ((->) r) -- Defined in `GHC.Base'
instance Monad IO -- Defined in `GHC.Base'
instance Monad [] -- Defined in `GHC.Base'
...plus two others
In the expression: return
In the expression: return $ map (^ 2) [0 .. 20]
In the second argument of defMethod', namely
`(\ _ -> return $ map (^ 2) [0 .. 20])'
/home/lowley/Documents/haskell/Qt/lancer-qml4.hs: line 11, column 27:
No instance for (Num b0) arising from a use of `^'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus three others
In the first argument of `map', namely `(^ 2)'
In the second argument of `($)', namely `map (^ 2) [0 .. 20]'
In the expression: return $ map (^ 2) [0 .. 20]
/home/lowley/Documents/haskell/Qt/lancer-qml4.hs: line 11, column 31:
No instance for (Enum b0)
arising from the arithmetic sequence `0 .. 20'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Enum Double -- Defined in `GHC.Float'
instance Enum Float -- Defined in `GHC.Float'
instance Integral a => Enum (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 7 others
In the second argument of `map', namely `[0 .. 20]'
In the second argument of `($)', namely `map (^ 2) [0 .. 20]'
In the expression: return $ map (^ 2) [0 .. 20]
I think the error is tiny, it should be quickly corrected but all my attempts were failures.
thanks you
EDIT:
for informations:
Prelude> let liste=[0..20] in map (^2) liste
[0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400]
Prelude>
I tried :
defMethod' "init_tableau" (\_ ->
let a=map (^2) [0..20]
in return a)]
with roughly the same error
EDIT 2:
Prelude> :t map (^ 2) [0..20]
map (^ 2) [0..20] :: (Enum b, Num b) => [b]
EDIT 3:
with this code:
main :: IO ()
main = do
clazz <- newClass [
defMethod' "init_tableau" (\_ ->
return ( map (^2) [0..20] ) :: IO [Integer] )]
ctx <- newObject clazz ()
runEngineLoop defaultEngineConfig {
initialDocument = fileDocument "exemple4.qml",
contextObject = Just $ anyObjRef ctx}
I've got this error:
/home/lowley/Documents/haskell/hsqml-demo-samples-0.3.4.0/qml/tableau1.hs:11:9:
Couldn't match type `MarshalMode Integer ICanReturnTo ()'
with `Yes'
In the expression:
defMethod'
"init_tableau"
(\ _ -> return (map (^ 2) [0 .. 20]) :: IO [Integer])
In the first argument of `newClass', namely
`[defMethod'
"init_tableau"
(\ _ -> return (map (^ 2) [0 .. 20]) :: IO [Integer])]'
In a stmt of a 'do' block:
clazz <- newClass
[defMethod'
"init_tableau"
(\ _ -> return (map (^ 2) [0 .. 20]) :: IO [Integer])]
I still can't resolve it.
I have not tested this, but I suspect the problem here is that there are many appropriate monads that could be used. If you want to be completely parallel to the working example, you can explicitly choose to use IO as the monad by adding a type annotation to the return expression:
return $ map (^2) [0..20] :: IO [Integer]
Daniel Wagner's suggestion fixes the error you asked about.
You now have another, unrelated error:
Couldn't match type `MarshalMode Integer ICanReturnTo ()' with `Yes'
Now consider the type
defMethod' :: (Typeable obj, MethodSuffix ms) => String -> (ObjRef obj -> ms) -> Member obj
You are attempting to pass (\_ -> return ( map (^2) [0..20] ) :: IO [Integer] ) to that as the second argument.
So can we unify ObjRef obj -> ms with forall a. a -> IO [Integer]?
Well, the first part unifies because a is free. But is IO [Integer] an instance of MethodSuffix? Follow the typeclasses and you'll see this requires that [Integer] be an instance of Marshal and follow that and you'll see we can't do that. I didn't see a good listing of the basic instances of Marshal in the docs, but I did find them in the source.
So it seems if instead of [Integer] you try to return [Int] or Text, then this will likely typecheck.
Use recursion and list pattern matching to define a function exists with the following type:
exists : (’a -> bool) -> ’a list -> bool
The function should have the following behavior: for any predicate (function with boolean range) p and list l, a well-typed invocation (exists p l) should evaluate to true iff there exists some element x of l for which p x evaluates to true.
I am new to OCaml and do not know where to begin, any help would be great.
#let rec exists p = function
[] -> false
| x::_ when p x -> true
| _::tl -> exists p tl;;
val exists : ('a -> bool) -> 'a list -> bool = <fun>
test :
# exists ((=)2) [4;3;2;1];;
- : bool = true
# exists ((=)2) [1;4];;
- : bool = false
About pattern matching :
let is_one = function
1 -> true
| x -> false
or
let is_one = function
1 -> true
| _ -> false (* _ in any case *)
or
let is_one = function
x when x=1 -> true
| _ -> false
test
# is_one 1;;
- : bool = true
How could i print the results of this function find_simple_stmt_nodes : (t -> Cil_types.stmt -> PdgTypes.Node.t list) Pervasives.ref.Is there a method to do that? If anybody could help me... I tried something like that:
let listeStatement= !Db.Pdg.find_simple_stmt_nodes pdg assert_stmt in
let rec print_list = function
[] -> ()
| x :: l -> Format.printf "%a#." (!Db.Pdg.pretty_node false) x;
print_string " "; Format.printf "%a#." (!Db.Pdg.pretty_node false) l in
print_list listeStatement;;