Is the following function tail recursive? - recursion

I have a function in which the starred line is a conjunction involving a recursive call. As conjunctions work, if h1 <> h2 then the recursive call will not be made. But if the call is made, then will the compiler still backtrack and perform a whole bunch of conjunctions over true values? Or will it elide this unnecessary step?
In other words, is the following function effectively tail recursive?
let isExtensionOf<'A when 'A : equality> (lst1 : list<'A>) (lst2 : list<'A>) : bool =
let rec helper (currLst1 : list<'A>) (currLst2 : list<'A>) : bool =
match currLst1, currLst2 with
| h1 :: _, [] -> false
| [], _ -> true
| h1 :: t1, h2 :: t2 -> (h1 = h2) && (helper t1 t2) // *
helper lst1 lst2
Yes, I know that the starred line should be written if h1 = h2 then helper t1 t2 else false. But I am just curious.
Thanks in advance.

Another easy trick to find out whether the function is tail-recursive is to throw an exception and look at the stack trace. For example, you can modify helper as follows:
let rec helper (currLst1 : list<'A>) (currLst2 : list<'A>) : bool =
match currLst1, currLst2 with
| h1 :: _, [] -> failwith "!"
| [], _ -> failwith "!"
| h1 :: t1, h2 :: t2 -> (h1 = h2) && (helper t1 t2)
If you now call helper [1..10] [1..10], you get a stack trace that looks like this:
System.Exception: !
at FSI_0002.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at .$FSI_0003.main#()
Stopped due to error
But if you change the code to be non-tail-recursive - e.g. by modifying the last line to make the recursive call first (helper t1 t2) && (h1 = h2), then the stack trace shows all the recursive calls:
System.Exception: !
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at FSI_0004.helper[A](FSharpList'1 currLst1, FSharpList'1 currLst2) in test.fsx:line 4
at .$FSI_0005.main#()

From ILSpy it would appear so:
IL_0000: nop
IL_0001: newobj instance void class '<StartupCode$ConsoleApplication3>.$Program'/helper#10<!!A>::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldarg.1
IL_0009: ldarg.2
IL_000a: tail.
IL_000c: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!!A>, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!!A>>::InvokeFast<bool>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!1, !!0>>, !0, !1)
IL_0011: ret

Related

Clojure - filter nested map on innermost level

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))]))))))

Idris - erasure of indices fails

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 ?

No instance for (Monad m0) arising from a use of `return'

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.

OCaml Function Writing: Use recursion and list pattern matching to define a function exists with the following type:

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

Printing the results of the method find_simple_stmt_nodes (Module Db.Pdg)

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;;

Resources