Sum of a 4-elem float tuple in OCaml - tuples

I need to write a function that takes a four-element real number tuple as input, and at the output it returns the sum of these numbers.
  For example:
  calling: sum (3., 2., 5., 1) ;;
  result: 11.
I know this works:
(fun (x,y,z,u) -> x+y+z+u) (4,5,6,7);;
But I want to be able to enter the numbers later.
Edit, my little next question: There are only fst and snd selectors in OCaml, am I right?

Well, the code you give uses a function expression (also known as a lambda) and doesn't give the function a name.
If you want to call the function later you just need to give it a name. You can use exactly the same expression if you want to:
let sum = fun (x, y, z, u) -> x + y + z + u
(There is some type disagreement between your description of the problem and this solution.
It's true, there are no pre-defined OCaml functions for retrieving components of tuples with more than 2 elements. You can easily write your own, of course:
let fst3 (a, b, c) = a
let snd3 (a, b, c) = b
let thd3 (a, b, c) = c

Related

Write a predicate called rlen(X,N) to be true when N counts the total number of occurrences of atoms in the list X

I want to get this solution for my question. For example, ?- rlen([a,[a,b],c],X). returns X = 4. I tried the following code but it returns answer 3. Maybe, it's taking [a,b] as one element. I am new to prolog and learning, any help would be really appreciated.
rlen([],0).
rlen([_|T],N) :- rlen(T,N1),N is N1+1.
The code you wrote returns the number of elements in a list and [a,[a,b],c] has exactly 3 elements: a, [a,b] and c. If you want to do a nested count, I would suggest using the build-in predicate flatten/2 to flatten the list.
example (tested with SWISH):
?- rlen([a,[a,b],c],X).
X = 3.
?- flatten([a,[a,b],c],L).
L = [a, a, b, c].
?- flatten([a,[a,b],c],L), rlen(L,N).
L = [a, a, b, c],
N = 4.
However not using inbuild predicates is a bit more challenging, because you have to go through your list like in any normal length predicate, and for every Head element you have to distinguish between the case that the head element is a list or is not a list. If A is a list, count the elements of A, otherwise just add 1. (a -> b ; c ) is an if-then else: if a, then b, else c. Tested with SWISH:
rlen([],0).
rlen([A|T],N) :-
( is_list(A)
-> rlen(A,NA)
; NA is 1
),
rlen(T,NT),
N is NA+NT.
?- rlen([a,[a,b],c],X).
X = 4.

How do I combine consectuive numbers in a list into a range in Haskell?

I'm trying to grapple my head around Haskell and I'm having a hard time pinning down the general procedure/algorithm for this specific task. What I want to do is basically give Haskell a list [1,2,3,5,6,9,16,17,18,19] and have it give me back [1-3, 5, 6, 9, 16-19] so essentially turning three or more consecutive numbers into a range in the style of lowestnumber - highestnumber. What I have issue with it I suppose is the all too common difficulty grappling with with the functional paradigm of Haskell. So I would really appreciate a general algorithm or an insight into how to view this from an "Haskellian" point of view.
Thanks in advance.
If I understand the question correctly, the idea is to break up the input lists in chunks, where a chunk is either a single input element or a range of at least three consecutive elements.
So, let's start by defining a datatype for representing such chunks:
data Chunk a = Single a | Range a a
As you can see, the type is parametric in the type of input elements.
Next, we define a function chunks to actually construct a list of chunks from a list of input elements. For this, we require the ability to compare input elements and to obtain the immediate consecutive for a given input element (that is, its successor). Hence, the type of the function reads
chunks :: (Eq a, Enum a) => [a] -> [Chunk a]
Implementation is relatively straightforward:
chunks = foldr go []
where
go x (Single y : Single z : cs) | y == succ x && z == succ y = Range x z : cs
go x (Range y z : cs) | y == succ x = Range x z : cs
go x cs = Single x : cs
We traverse the list from right to left, generating chunks as we go. We generate a range if an input element precedes its two immediate consecutive elements (the first case of the helper function go) or if it precedes a range that starts with its immediate consecutive (the second case). Otherwise, we generate a single element (the final case).
To arrange for pretty output, we declare applications of the type constructor Chunk to be instances of the class Show (given that the type of input elements is in Show):
instance Show a => Show (Chunk a) where
show (Single x ) = show x
show (Range x y) = show x ++ "-" ++ show y
Returning to the example from the question, we then have:
> chunks [1,2,3,5,6,9,16,17,18,19]
[1-3,5,6,9,16-19]
Unfortunately, things are slightly more complicated if we need to account for bounded element types; such types have a largest element for which succ is undefined:
> chunks [maxBound, 1, 2, 3] :: [Chunk Int]
*** Exception: Prelude.Enum.succ{Int}: tried to take `succ' of maxBound
This suggests that we should abstract from the specific approach for determining whether one elements succeeds another:
chunksBy :: (a -> a -> Bool) -> [a] -> [Chunk a]
chunksBy succeeds = foldr go []
where
go x (Single y : Single z : cs) | y `succeeds` x && z `succeeds` y =
Range x z : cs
go x (Range y z : cs) | y `succeeds` x = Range x z : cs
go x cs = Single x : cs
Now, the version of chunks that was given above, can be expressed in terms of chunksBy simply by writing
chunks :: (Eq a, Enum a) => [a] -> [Chunk a]
chunks = chunksBy (\y x -> y == succ x)
Moreover, we can now also implement a version for bounded input types as well:
chunks' :: (Eq a, Enum a, Bounded a) => [a] -> [Chunk a]
chunks' = chunksBy (\y x -> x /= maxBound && y == succ x)
That merrily gives us:
> chunks' [maxBound, 1, 2, 3] :: [Chunk Int]
[9223372036854775807,1-3]
First, all elements of a list must be of the same type. Your resulting list has two different types. Ranges (for what ever that means) and Ints. We should convert one single digit into a range with lowest and highest been the same.
Been said so, You should define the Range data type and fold your list of Int into a list of Range
data Range = Range {from :: Int , to :: Int}
intsToRange :: [Int] -> [Range]
intsToRange [] = []
intsToRange [x] = [Range x x]
intsToRange (x:y:xs) = ... -- hint: you can use and auxiliar acc which holds the lowest value and keep recursion till find a y - x differece greater than 1.
You can also use fold, etc... to get a very haskelly point of view
Use recursion. Recursion is a leap of faith. It is imagining you've already written your definition and so can ("recursively") call it on a sub-problem of your full problem, and combine the (recursively calculated) sub-result with the left-over part to get the full solution -- easy:
ranges xs = let (leftovers, subproblem) = split xs
subresult = ranges subproblem
result = combine leftovers subresult
in
result
where
split xs = ....
combine as rs = ....
Now, we know the type of rs in combine (i.e. subresult in ranges) -- it is what ranges returns:
ranges :: [a] -> rngs
So, how do we split our input list xs? The type-oriented design philosophy says, follow the type.
xs is a list [a] of as. This type has two cases: [] or x:ys with x :: a and ys :: [a]. So the easiest way to split a list into a smaller list and some leftover part is
split (x:xs) = (x, ys)
split [] = *error* "no way to do this" -- intentionally invalid code
Taking note of the last case, we'll have to tweak the overall design to take that into account. But first things first, what's the rngs type could be? Going by your example data, it's a list of rngs, naturally, rngs ~ [rng].
A rng type though, we have a considerable degree of freedom to make it to be whatever we want. The cases we have to account for are pairs and singletons:
data Rng a = Single a
| Pair a a
.... and now we need to fit the jagged pieces together into one picture.
Combining a number with a range which starts from consecutive number is obvious.
Combining a number with a single number will have two obvious cases, for whether those numbers are consecutive or not.
I think / hope you can proceed from here.

Reduce a list with entries made up of Bool and Rational values in Haskell

I got a list that contains entries which are made up of a Bool and a Rational value that looks like this:
[(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40),
(False,1 % 40),(False,9 % 40),(False,1 % 40),(True,9 % 40)]
I want to reduce the entries that share a Bool value into one and also add up the corresponding Rational values.
The result for the above example should look like this:
[(False,31 % 40),(True,9 % 40)]
I am new to Haskell and tried to accomplish the task using foldM, but I don't think that's the right way to do it.
Any help is much appreciated.
You can indeed use a fold here. I would here use a 2-tuple where for example the first element contains the sum of the Falses, and the second the sum of the Trues:
import Control.Arrow(first, second)
import Data.Bool(bool)
dsum :: (Foldable f, Num a) => f (Bool, a) -> (a, a)
dsum = foldr (uncurry ((. (+)) . bool first second)) (0,0)
For a foldable of (Bool, a) tuples, it will thus calculate a 2-tuple where the first element contains the sum of the (False, ...) tuples, and the second the sum of the (True, ...) tuples.
Here the (uncurry ((. (+)) . bool first second)) is a compact representation of a function f:
f :: Num a => (Bool, a) -> (a, a) -> (a, a)
f (False, d) (a, b) = (d+a, b)
f (True, d) (a, b) = (a, d+b)
For example:
Prelude> d = [(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40), (False,1 % 40),(False,9 % 40),(False,1 % 40),(True,9 % 40)]
Prelude> dsum d
(31 % 40,9 % 40)
By using a 2-tuple, we thus add a "contract" that we will have exactly two elements, which is usually preferrable over a list that will always contain two items.
I think with foldM you are already going in the right direction - although the M is not necessary as your function can be implemented purely - i.e. without side effects.
I would use a Map Bool Rational (from the containers package) for the accumulator - as this can be generalized easily if your tuples have a more complex type in the first position.
import qualified Data.Map as M
processList :: (Ord k, Bounded k, Enum k, Num v) => [(k,v)] -> [(k,v)]
processList = M.toList . foldr' (uncurry (M.insertWith (+))) init
where init = M.fromList [(x,0) | x <- [minBound..maxBound] ]
alternatively you can use
where init = M.empty
if you don't want default values (0%1) in the list, then you can also drop the Enum and Bounded constraints
I think the solution below is more appropriate for beginners but it won't work if your list has no tuples with either True or False (you can solve this easily. Give it a try ;) )
sumBooleans :: (Num a) => [(Bool,a)] -> [(Bool,a)]
sumBooleans l = map (foldr1 sumTuples) grouppedList
where sumTuples (b,r) (_, r') = (b, r + r')
grouppedList = groupBy myCondition l
myCondition (b,_) (b', _) = b == b'
So grouppedList is a list containing two list. One list is all "True tuples", and the other is all "False tuples". Then you reduce each list using foldr1 sumTuples (you have to map this foldr1 sumTuples because you have a list of lists).
Have you considered that a list is not the best data structure for the output of your function?
Best,

convert a few 2-tuples to a list of lists

this is a question about ocaml lists and tuples. I have some 2-tuples of numbers (either integers or floats) and I want to convert it to a list of lists (with 2 elements). Assuming that I have defined a num type Int of int | Float of float, the conversion should give the following:
((1,1.0),(0.4,1),(0,0)) => [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
or more precisely
let a = (1,1.0) and b = (0.4,1) and c = (0,0) in
myconversion (a,b,c) ;;
=> [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
the point being the values a, b, c... are defined in several places in the source files (by people who use different signatures for their tuples).
The difficulty here is that I don't know the types of the elements of the 2-tuples (int or float, that varies depending on the tuple).
Your input data can't be represented in OCaml as you describe it. OCaml is strongly typed. For example, your example input list is an invalid value in OCaml:
# [(1,1.0);(0.4,1);(0,0)];;
Error: This expression has type float but an expression was expected of type
int
So what you describe as the essence of your problem (not knowing the types) is in fact not possible. You'll have to use some other method of representing the input. For example, you could just use floats for everything. Or you could use pairs of strings.
Update
The answer for the rewritten question is the same. In OCaml it's not possible not to know the type of something statically; i.e., at the time you're writing the program (unless it can be any type at all). It's not possible (or necessary) to query the type of something at runtime. So your question doesn't have an answer (at least as far as I can see).
For OCaml, you have to think with the type system rather than against it. After a while you start to really like it (or at least that's how it worked for me). I'd start by writing down the type you want your function myconverstion to have.
Update 2
I'll repeat my advice to treat your inputs as strings. Assuming you've parsed your input up into pairs of strings, here's some code that does what you want:
let myconversion coords =
let c1 s =
if String.contains s '.' then
Float (float_of_string s)
else
Int (int_of_string s)
in
let cp (a, b) = [c1 a; c1 b] in
List.map cp coords
Here's how it works for your input (reinterpreted as strings):
# myconversion [("1", "1.0"); ("0.4", "1"); ("0", "0")];;
- : fi list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
Update 3
Here's some (crude) code that parses a file of numbers into coordinates represented as pairs of strings. It should work as long as the tuples in the input are well formed.
let coords fname =
let ic = open_in fname in
let len = in_channel_length ic in
let buf = Buffer.create 128 in
let () = Buffer.add_channel buf ic len in
let () = close_in ic in
let s = Buffer.contents buf in
let nums = Str.(split (regexp "[^0-9.]+") s) in
let rec mkcoords sofar = function
| [] | [_] -> List.rev sofar
| a :: b :: rest -> mkcoords ((a, b) :: sofar) rest
in
mkcoords [] nums
There are two distinct problems in your setup:
you don't know the type of the tuples parameters
you want to pass them as a single n-ary tuple
For problem 2, you would have to write a function for that type specifically, whereas you could mimic a type level list type by nesting couple of tuples:
myconversion a,(b,c) ;;
The reason is that with that setup, you could write a recursive polymorphic function on the type level list:
val myconversion : type a b. (a,b) -> num list
There would still be a problem on the last element though.
So, assuming that you could pass a sequence to your conversion function, and have it process elements of that sequence one by one, you would still need to find a way of selecting the proper function of pair conversion from the tuple type: that's basically ad-hoc polymorphism, ie. you would need to be able to overload a function on its parameters' types(1). Unfortunately, OCaml doesn't support that out of the box.
One possibility would be perhaps (I have no experience doing that) to implement an extension which would extract the type information of a given expression, and generate the correct code to process it in your own code.
A flexible technique consists in having that extension generate an algebraic description of the tuples types, and use that description as an equality witness in the code which will process the tuples:
type _ w =
| U : (unit * unit) w
| IF : 'a w -> ((int * float) * 'a) w
| FI : 'a w -> ((float * int) * 'a) w
(* other constructors if necessary *)
(* data *)
let a = 1,1.0
let b = 2.0, 2
let c = 3.0, 3
let d = 4, 4.0
let l = a,(b, (c,(d,((),()))))
(* witness *)
let w = IF (FI (FI (IF U)))
(* the type parameter of w should be the same as l type *)
let rec conv : type a b. (a * b) w -> (a * b) -> num list = fun w (x, xs) ->
match w with
U -> []
| IF w' -> let i,f = x in (Int I)::(Float f)::(conv w' xs)
(* etc *)
Here, we encode the type level nil list as (unit * unit) w.
A coalgebraic approach would require to register function overloads to the conversion function polymorphic signature within the extension, and let it pick the right one from the function overload dictionary.
There's a discussion on that topic on the LtU site.
Thanks to everybody who answered. I finally found a solution, using a bit of magic:
# type num = Int of int | Float of float;;
# let to_num x = if Obj.is_int (Obj.repr x) then
Int (Obj.magic (Obj.repr x) : int)
else
Float ((Obj.magic (Obj.repr x) : float));;
# let pair_to_num (a,b) = [to_num a; to_num b];;
# let myconversion (a,b,c) = [pair_to_num a; pair_to_num b; pair_to_num c];;
and the test:
# myconversion ((1,1.0),(0.4,1),(0,0));;
- : num list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
# myconversion ((0,0),(1,1.0),(0.4,1));;
- : num list list = [[Int 0; Int 0]; [Int 1; Float 1.]; [Float 0.4; Int 1]]
Magic, the order does not matter and the type is recorded! I can then follow didier's idea to get rid of the pair of superfluous parentheses.

Ocaml : function that two integers and returns the list of all integers in the range

This function takes two integers and returns the list of all integers in the range [a,b]
This is the solution that I wrote.
let rec range_rec l a b =
if (a=b) then l#[b]
else range_rec (l#[a], a+1, b);;
let range a b = range_rec [] a b;;
I'm hitting an error "Error: This expression has type int list * int * int but an expression was expected of type int". Can someone throw some light on why am I getting this error?
Thanks.
It should look like this:
let rec range_rec l a b =
if a = b then l # [b]
else range_rec (l # [a]) (a + 1) b;;
let range a b = range_rec [] a b;;
What I've done:
Changed loop to range_rec
Changed (l#[a], a+1, b) to (l # [a]) (a + 1) b. The first is a triplet and the second is 3 arguments to a curried function.
Notice that if (a = b) then can be written as if a = b then.
Last, the function can be made more efficient by using :: instead of # by looping "backwards". For example like gasche have shown.
The l # [elem] operation is terrible from a performance perspective : as a # b is linear in the length of a, adding an element to the end of list is linear in the length of the list, making your whole range_rec definition quadratic in |b-a|. The way to go is to change your code so that you can use the constant-time elem::l operation instead.
let rec range a b =
if a > b then []
else a :: range (a + 1) b
You may make additional optimizations such as making it tail-recursive, but at least the complexity of this solution is right.
To improve on the solution already suggested by gasche, this can be made tail-recursive.
let int_range a b =
let rec int_range_rec l a b =
if a > b then l
else int_range_rec (b :: l) a (b - 1)
in (int_range_rec [] a b);;