totality checking with indirect mutually recursive datatypes in Idris - idris

I am working with an abstract syntax tree, where I'd like to give the binders their own type. This seems to cause problems for Idris's totality checking...
With a typical self-referencial Tree Idris does fine with totality checking.
data TreeShape = Last | More TreeShape TreeShape
Show TreeShape where
show Last = "Leaf"
show (More left right) = "Branch " ++ show left ++ " " ++ show right
Likewise with a mutual Tree:
mutual
data MuTree = Another MuMuTree
data MuMuTree = TheLeaf | TheBranch MuTree MuMuTree
Show MuTree where
show (Another x) = show x
Show MuMuTree where
show TheLeaf = "Leaf"
show (TheBranch left right) = "Branch " ++ show left ++ " " ++ show right
But, introduce indirection by paramaterizing the extracted type, and totality checking fails:
data LeftBranch t = L t
(Show t) => Show (LeftBranch t) where
show (L x) = show x
data TreeOutline = Final | Split (LeftBranch TreeOutline) TreeOutline
Show TreeOutline where
show Final = "Leaf"
show (Split left right) = "Branch " ++ show left ++ " " ++ show right
Is there a way to get Idris to properly check totality on recursive types of the last sort? Short of that, is there something other than sprinkling the code with assert_totals?

Related

List split in Elm

Write a function to split a list into two lists. The length of the first part is specified by the caller.
I am new to Elm so I am not sure if my reasoning is correct. I think that I need to transform the input list in an array so I am able to slice it by the provided input number. I am struggling a bit with the syntax as well. Here is my code so far:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
So I am thinking to return a list containing 2 lists(first one of the specified length), but I am stuck in the syntax. How can I fix this?
Alternative implementation:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
I'll venture a simple recursive definition, since a big part of learning functional programming is understanding recursion (which foldl is just an abstraction of):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)
Use List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
When list p reaches the desired length, append element x to the second list q.
Append element x to list p otherwise.
Normally in Elm, you use List for a sequence of values. Array is used specifically for fast indexing access.
When dealing with lists in functional programming, try to think in terms of map, filter, and fold. They should be all you need.
To return a pair of something (e.g. two lists), use tuple. Elm supports tuples of up to three elements.
Additionally, there is a function splitAt in the List.Extra package that does exactly the same thing, although it is better to roll your own for the purpose of learning.

Why does comb behave differently inside the loop?

Note: I'm doing this all from the REPL using
This is Rakudo Star version 2019.03.1 built on MoarVM version 2019.03
implementing Perl 6.d.
From euler project #22 there is a names.txt file similar to
"JERE","HAI","ELDEN","DORSEY","DARELL","BRODERICK","ALONSO", ...
When I read that in, split and sort it I get the list of names as I'd expect.
for '../names.txt'.IO.slurp.split(',').sort -> $name {
say $name;
}
That prints out
...
"ZONIA"
"ZORA"
"ZORAIDA"
"ZULA"
"ZULEMA"
"ZULMA"
Now if I add comb()
for '../names.txt'.IO.slurp.split(',').sort -> $name {
say $name.comb;
}
I'm getting
...
(" Z O N I A ")
(" Z O R A ")
(" Z O R A I D A ")
(" Z U L A ")
(" Z U L E M A ")
(" Z U L M A ")
However, if I just run from the repl;
> "ZULMA".comb
I get
(Z U L M A) # Note the lack of quotes
Why is comb behaving differently in these two scenarios?
It's not behaving differently. In one case the quotes are a syntax element - part of the code - and in the other case data read verbatim from the file:
"ZULMA".comb
'"ZULMA"'.comb
The data is different. not the behaviour.

Infinite Type error while attempting exercise in Binary Tree example

In working through Exercise 2 here, I offered this solution to the compiler and got an Infinite Type error.
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: flatten left :: flatten right
This doesn't seem too different from my solution to the first exercise:
sum : Tree Int -> Int
sum tree =
case tree of
Empty -> 0
Node v left right ->
v + sum left + sum right
I wondered if perhaps the issue had to do with order of operations, so I added parens to ensure flatten gets evaluated before ::, but this doesn't seem to make a difference:
flatten : Tree a -> List a
flatten tree =
case tree of
Empty -> []
Node v left right ->
[v] :: (flatten left) :: (flatten right)
So now I'm just stumped.
:: is the cons operator, which means it will prepend a single element onto a list. Its type signature is a -> List a -> List a. That means this isn't valid code since the first argument, [v] is a list:
[v] :: flatten left :: flatten right -- invalid!
If you want to concatenate two lists, you use the concatenation operator: ++. You could just replace :: with ++ in your example to get it to compile:
[v] ++ flatten left ++ flatten right
Another way to represent that line is to concatenate the two lists, then prepend the list with v using the cons operator.
v :: flatten left ++ flatten right
-- The following is the same as above, but with parentheses showing precedence
v :: (flatten left ++ flatten right)
There are more efficient ways to do this, of course, but it highlights the difference between cons and concatenation.
The reason your sum example works is because it is returning an int instead of a list of ints. The type you are returning in sum is the same as the value in the tree, so you end up with an aggregate, not another list.

Syntax errors in sml: Inserting LOCAL

The following method determines how many numbers can be added up starting from the beginning of the list without adding up to 4:
number_before_Reaching_sum (4, [1,2,3,4,6]);
should return : val it = 2 : int
fun number_before_reaching_sum (sum : int * int list) =
let val len_orig_list = length (#2 sum)
in fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
end
syntax error: inserting LOCAL
syntax error found at EOF
I can't seem to find the errors in this code. I have some experience with Python, but just starting to learn sml. I'm loving it, but I don't understand all the error messages. I have really spent hours on this, but I think I don't know enough to solve my problem. I tried exchanging let with local, but i still got a syntax error (equalop). I think that the function between in and end is an expression and not a declaration. But I would appreciate any comments on this. If you come up with alternative code, it would be great if you did it without using more advanced features, since I'm just trying to get the basics down :-)
You probably meant this:
fun number_before_reaching_sum (sum : int * int list) =
let
val len_orig_list = length (#2 sum)
fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
in
num_bef_reach_sum (sum)
end
With let … in … end, the part between let and in is for the local definitions; the part between in and end is for the expression which will be the evaluation of the let … in … end expression (this construct is indeed an expression).
Think of let … in … end as a possibly complex expression. You hoist parts of the expression as definitions, then rewrite the complex expression using references to these definitions. This help write shorter expressions by folding some of its sub‑expressions. This construct is also required when recursion is needed (a recursion requires a defining name).
Another way to understand it, is as the application of an anonymous function whose arguments bindings are these definitions.
Ex.
let
val x = 1
val y = 2
in
x + y
end
is the same as writing
(fn (x, y) => x + y) (1, 2)
which is the same as writing
1 + 2
You erroneously put a definition at the place of the expression the whole evaluates to.
(note I did not check the function's logic, as the question was about syntax)

Find all Change Combinations (money) in OCaml

I have a some OCaml code that finds all combinations of change given a change amount. I have most of the code working, however I am not able to figure out how this recursive function will actually return the possible change combinations.
let change_combos presidents =
let rec change amount coinlist = match amount with
|0 -> [[]] (*exits when nothing*)
|_ when (amount < 0) -> [] (*exits when less than 0*)
|_ -> match coinlist with
|[] -> [] (*Returns empty list, exits program*)
(*h::f -> something, using [25;10;5;1] aka all change combinations...*)
(*using recursion, going through all combinations and joining lists returned together*)
let print_the_coin_matrix_for_all_our_joy enter_the_matrix =
print_endline (join "\n" (List.map array_to_string enter_the_matrix));;
Thanks for the help, let me know if I need to clarify something :)
It is a bit confusing what you're looking for. I believe that you want to generate a list of all the combinations of a list? You should think about the recursion and how to generate the individual elements. Start with the input type, and how you'd generate successive elements by reducing the problem space.
let rec generate lst = match lst with
| [] -> []
| h::t -> [h] :: (List.map (fun x -> h::x) (generate t)) # (generate t)
If the list is [] there are no combinations. If we have an element we generate all combinations without that element and base our construction on that assumption. The components fall into place at this point. Concatenate the list of combinations of t with the combinations of t and h cons'd onto each and a singleton of h.