F# Sort an Array with foldBack or fold. - arrays

I am trying to sort an Array by using fold or foldBack.
I have tried achieving this like this:
let arraySort anArray =
Array.fold (fun acc elem -> if acc >= elem then acc.append elem else elem.append acc) [||] anArray
this ofcourse errors horribly. If this was a list then i would know how to achieve this through a recursive function but it is not.
So if anyone could enlighten me on how a workable function given to the fold or foldback could look like then i would be createful.
Before you start advising using Array.sort anArray then this wont do since this is a School assignment and therefore not allowed.

To answer the question
We can use Array.fold for a simple insertion sort-like algorithm:
let sort array =
let insert array x =
let lesser, greater = Array.partition (fun y -> y < x) array
[| yield! lesser; yield x; yield! greater |]
Array.fold insert [||] array
I think this was closest to what you were attempting.
A little exposition
Your comment that you have to return a sorted version of the same array are a little confusing here - F# is immutable by default, so Array.fold used in this manner will actually create a new array, leaving the original untouched. This is much the same as if you'd converted it to a list, sorted it, then converted back. In F# the array type is immutable, but the elements of an array are all mutable. That means you can do a true in-place sort (for example by the library function Array.sortInPlace), but we don't often do that in F#, in favour of the default Array.sort, which returns a new array.
You have a couple of problems with your attempt, which is why you're getting a few errors.
First, the operation to append an array is very different to what you attempted. We could use the yield syntax to append to an array by [| yield! array ; yield element |], where we use yield! if it is an array (or in fact, any IEnumerable), and yield if it is a single element.
Second, you can't compare an array type to an element of the array. That's a type error, because compare needs two arguments of the same type, and you're trying to give it a 'T and a 'T array. They can't be the same type, or it'd be infinite ('T = 'T array so 'T array = 'T array array and so on). You need to work out what you should be comparing instead.
Third, even if you could compare the array to an element, you have a logic problem. Your element either goes right at the end, or right at the beginning. What if it is greater than the first element, but less than the last element?
As a final point, you can still use recursion and pattern matching on arrays, it's just not quite as neat as it is on lists because you can't do the classic | head :: tail -> trick. Here's a basic (not-so-)quicksort implementation in that vein.
let rec qsort = function
| [||] -> [||]
| arr ->
let pivot = Array.head arr
let less, more = Array.partition (fun x -> x < pivot) (Array.tail arr)
[| yield! qsort less ; yield pivot ; yield! qsort more |]
The speed here is probably several orders of magnitude slower than Array.sort because we have to create many many arrays while doing it in this manner, which .NET's Array.Sort() method does not.

Related

Check if a list and array are equal F#

I am trying to compare a list and an array and see if they are equal. Lets say we have a list list = [1;2;3;4] and an array ar = [|1;2;3;4|]. The function should return true if equal and false if not equal. I did it like this:
let list = [1;2;3;4]
let ar = [|1;2;3;4|]
let list' = Array.toList ar
(list = list')
So basically what I am doing is simply convert and compare two lists.. My question is is there any other way to do this, I mean which do not simply convert between list and array and which do not rely entirely on library functions.
You can use the fact that both lists and arrays (as well as most other collections) implement the seq<'a> interface (IEnumerable<T> in the .NET terms) and so you can just pass them to the functions from the Seq module without any conversions. This is just using an interface, so there is no overhead.
The easiest function I can think of for checking whether two sequences are the same is forall2, which takes two sequences and checks that a predicate holds for the elements pairwise. In this case, the predicate is just equality test (fun a b -> a = b) which you can abberviate as (=):
let list = [1;2;3;4]
let ar = [|1;2;3;4|]
Seq.forall2 (=) list ar
There are lots of ways you could do this. Here's one that compares the elements pairwise:
if list.Length = ar.Length then
Seq.zip list ar
|> Seq.forall (fun (a, b) -> a = b)
else false
F# docs say:
You compare two sequences by using the Seq.compareWith function. The function compares successive elements in turn, and stops when it encounters the first unequal pair. Any additional elements do not contribute to the comparison.
Which in your case becomes oneliner:
0 = Seq.compareWith (Comparer<_>.Default) list ar
Didn't check if it compiles. Use the Comparer.Default to compare primitives, otherwise, for complex custom types you may need to provide your own.
With Linq;
Enumerable.SequenceEqual (list, ar)
Based on this
let l = [1;2;3;4]
let a = [|1;2;3;4|]
let result = Seq.compareWith Operators.compare l a

list of subarrays of an array

I am trying to implement a function stride n a where n is a stride length and a is an array. Given a call like stride 2 [| "a"; "b"; "c"; "d" |] it should return something like [ [|"a"; "b"|]; [|"c"; "d" |] ]. I am brand new to F# and don't know anything about using arrays in a functional language. I know what I've written is garbage, but it's a start:
let stride n (a : array 'a) =
let rec r ind =
if ind >= a.length()
then
[]
else
a[ind .. (ind + n - 1)]::r(ind + n)
in
r 0
(see also on dotnetfiddle). This does not compile. I to added the array 'a type parameter because the compiler couldn't find the length method, but this type parameter does not appear to be allowed.
For context, I am trying to get groups of letters from a string, so I plan to call this like stride 2 myString.ToCharArray().
First of all, there is already an app for that - it's called Array.chunkBySize:
> Array.chunkBySize 2 [|1;2;3;4;5;6;7|]
val it : int [] [] = [|[|1; 2|]; [|3; 4|]; [|5; 6|]; [|7|]|]
And there are similar functions in the Seq and List module, so if your goal is to work with strings, I would consider using the Seq variant, since string already implements the seq interface:
> Seq.chunkBySize 2 "abcdefg";;
val it : seq<char []> =
seq [[|'a'; 'b'|]; [|'c'; 'd'|]; [|'e'; 'f'|]; [|'g'|]]
But if you're interested in education rather than GSD, then here it is:
The logic of the code is fine, except you have a few purely syntactic mistakes and one logical.
First, the type "array of a" is not denoted array 'a. In general the F# notation for generic types is either T<'a> or 'a T, for example list<int> or int list. However, this doesn't work for arrays, because arrays are special. There is a type System.Array, but it's not generic, so you can't use it like that. Instead, the idea of an array is kind of baked into the CLR, so you have to use the special syntax, which is 'a[].
So: a : 'a[] instead of a : array 'a
Second while array does have a length property, it's capitalized (i.e. Length) and it's a property, not a method, so there shouldn't be parens after it.
So: a.Length instead of a.length()
However, that is not quite the F# way. Methods and properties are meh, functions are way better. The F# way would be to use the Array.length function.
So: Array.length a instead of a.length()
Bonus: if you do that, there is no need for the type annotation : 'a[], because the compiler can now figure it out from the type of Array.length.
Third, indexing of arrays, lists, and everything else that has an index, needs a dot before the opening bracket.
So: a.[ind .. (ind + n - 1)] instead of a[ind .. (ind + n - 1)]
Fourth, the in is not necessary in F#. You can just omit it.
With the above modifications, your program will work.
But only on arrays whose length is a multiple of n. On all others you'll get an IndexOutOfRangeException. This is because you also have...
The logical mistake is that while you're checking that ind is within the array bounds, you're not checking that ind + n - 1 is as well. So you need a third case in your branch:
if ind >= Array.length a then
[]
elif ind + n - 1 >= Array.length a then
a.[ind..] :: r (ind+n)
else
a.[ind .. (ind+n-1)] :: r (ind+n)
Now this is ready for prime time.

Haskell Array Pattern in a function

Hi total Haskell beginner here: What does the pattern in a function for an array look like ? For example: I simply want to add +1 to the first element in my array
> a = array (1,10) ((1,1) : [(i,( i * 2)) | i <- [2..10]])
My first thought was:
> arraytest :: Array (Int,Int) Int -> Array (Int,Int) Int
> arraytest (array (mn,mx) (a,b):xs) = (array (mn,mx) (a,b+1):xs)
I hope you understand my problem :)
You can't pattern match on arrays because the data declaration in the Data.Array.IArray module for the Array type doesn't have any of its data constructors exposed. This is a common practice in Haskell because it allows the author to update the internal representation of their data type without making a breaking change for users of their module.
The only way to use an Array, therefore, is to use the functions provided by the module. To access the first value in an array, you can use a combination of bounds and (!), or take the first key/value pair from assocs. Then you can use (//) to make an update to the array.
arraytest arr = arr // [(index, value + 1)]
where
index = fst (bounds arr)
value = arr ! index
If you choose to use assocs, you can pattern match on its result:
arraytest arr = arr // [(index, value + 1)]
where
(index, value) = head (assocs arr) -- `head` will crash if the array is empty
Or you can make use of the Functor instances for lists and tuples:
arraytest arr = arr // take 1 (fmap (fmap (+1)) (assocs arr))
You will probably quickly notice, though, that the array package is lacking a lot of convenience functions. All of the solutions above are fairly verbose compared to how the operation would be implemented in other languages.
To fix this, we have the lens package (and its cousins), which add a ton of convenience functions to Haskell and make packages like array much more bearable. This package has a fairly steep learning curve, but it's used very commonly and is definitely worth learning.
import Control.Lens
arraytest arr = arr & ix (fst (bounds arr)) +~ 1
If you squint your eyes, you can almost see how it says arr[0] += 1, but we still haven't sacrificed any of the benefits of immutability.
This is more like an extended comment to #4castle's answer. You cannot pattern match on an Array because its implementation is hidden; you must use its public API to work with them. However, you can use the public API to define such a pattern (with the appropriate language extensions):
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
-- PatternSynonyms: Define patterns without actually defining types
-- ViewPatterns: Construct patterns that apply functions as well as match subpatterns
import Control.Arrow((&&&)) -- solely to dodge an ugly lambda; inline if you wish
pattern Array :: Ix i => (i, i) -> [(i, e)] -> Array i e
-- the type signature hints that this is the array function but bidirectional
pattern Array bounds' assocs' <- ((bounds &&& assocs) -> (bounds', assocs'))
-- When matching against Array bounds' assocs', apply bounds &&& assocs to the
-- incoming array, and match the resulting tuple to (bounds', assocs')
where Array = array
-- Using Array in an expression is the same as just using array
arraytest (Array bs ((i,x):xs)) = Array bs ((i,x+1):xs)
I'm fairly sure that the conversions to and from [] make this absolutely abysmal for performance.

2d Array Sort in Haskell

I'm trying to teach myself Haskell (coming from OOP languages). Having a hard time grasping the immutable variables stuff. I'm trying to sort a 2d array in row major.
In java, for example (pseudo):
int array[3][3] = **initialize array here
for(i = 0; i<3; i++)
for(j = 0; j<3; j++)
if(array[i][j] < current_low)
current_low = array[i][j]
How can I implement this same sort of thing in Haskell? If I create a temp array to add the low values to after each iteration, I won't be able to add to it because it is immutable, correct? Also, Haskell doesn't have loops, right?
Here's some useful stuff I know in Haskell:
main = do
let a = [[10,4],[6,10],[5,2]] --assign random numbers
print (a !! 0 !! 1) --will print a[0][1] in java notation
--How can we loop through the values?
First, your Java code does not sort anything. It just finds the smallest element. And, well, there's a kind of obvious Haskell solution... guess what, the function is called minimum! Let's see what it does:
GHCi> :t minimum
minimum :: Ord a => [a] -> a
ok, so it takes a list of values that can be compared (hence Ord) and outputs a single value, namely the smallest. How do we apply this to a "2D list" (nested list)? Well, basically we need the minimum amongst all minima of the sub-lists. So we first replace the list of list with the list of minima
allMinima = map minimum a
...and then use minimum allMinima.
Written compactly:
main :: IO ()
main = do
let a = [[10,4],[6,10],[5,2]] -- don't forget the indentation
print (minimum $ map minimum a)
That's all!
Indeed "looping through values" is a very un-functional concept. We generally don't want to talk about single steps that need to be taken, rather think about properties of the result we want, and let the compiler figure out how to do it. So if we weren't allowed to use the pre-defined minimum, here's how to think about it:
If we have a list and look at a single value... under what circumstances is it the correct result? Well, if it's smaller than all other values. And what is the smallest of the other values? Exactly, the minimum amongst them.
minimum' :: Ord a => [a] -> a
minimum' (x:xs)
| x < minimum' xs = x
If it's not smaller, then we just use the minimum of the other values
minimum' (x:xs)
| x < minxs = x
| otherwise = minxs
where minxs = minimum' xs
One more thing: if we recurse through the list this way, there will at some point be no first element left to compare with something. To prevent that, we first need the special case of a single-element list:
minimum' :: Ord a => [a] -> a
minimum' [x] = x -- obviously smallest, since there's no other element.
minimum' (x:xs)
| x < minxs = x
| otherwise = minxs
where minxs = minimum' xs
Alright, well, I'll take a stab. Zach, this answer is intended to get you thinking in recursions and folds. Recursions, folds, and maps are the fundamental ways that loops are replaced in functional style. Just try to believe that in reality, the question of nested looping rarely arises naturally in functional programming. When you actually need to do it, you'll often enter a special section of code, called a monad, in which you can do destructive writes in an imperative style. Here's an example. But, since you asked for help with breaking out of loop thinking, I'm going to focus on that part of the answer instead. #leftaroundabout's answer is also very good and you fill in his definition of minimum here.
flatten :: [[a]] -> [a]
flatten [] = []
flatten xs = foldr (++) [] xs
squarize :: Int -> [a] -> [[a]]
squarize _ [] = []
squarize len xs = (take len xs) : (squarize len $ drop len xs)
crappySort :: Ord a => [a] -> [a]
crappySort [] = []
crappySort xs =
let smallest = minimum xs
rest = filter (smallest /=) xs
count = (length xs) - (length rest)
in
replicate count smallest ++ crappySort rest
sortByThrees xs = squarize 3 $ crappySort $ flatten xs

Haskell - check whether a 2D list has the same number of rows as columns

I have a 2D list [[Int]] in Haskell and I want to check two things:
whether the list has the sam number of rows as columns
whether the rows have the sam number of elements
For instance:
[[1,2,3], [1,55,9]] has the same number of rows as columns - here 2 - and each row has the same number of elements namely 3.
But
[[1,2], [1,55], [4,7]] has the same number of elements in each row though it has unequal number of rows and columns namely 3r 2c.
yet another example:
[[1,2], [1,55], [4,7,8]] has neither the same number of rows as columns nor each row has the same number of elements.
Actually step 1 includes step 2, am I right??
My attempt:
So what I attempted so far, is this:
listIsEqual :: [[Int]] -> Bool
listIsEqual myList = (all (\x -> length x == (length myList)) )
Right now I get the following error mesage:
Couldn't match expected type `Bool' with actual type `[a0] -> Bool'
In the return type of a call of `all'
Probable cause: `all' is applied to too few arguments
In the expression: (all (\ x -> length x == (length myList)))
In an equation for `listIsEqual':
listIsEqual myList = (all (\ x -> length x == (length myList)))
Could anyone tell me where the problem is?
Is there also any other ways to solve this problem?
GHC's error messages aren't always the most helpful, but in this case it got it right.
Probable cause: `all' is applied to too few arguments
And indeed, you forgot the second argument to all:
listIsEqual myList = all (\x -> length x == length myList) myList
^^^^^^
For the second task, you can map the length of every row (the number of columns in that row) defining a function
let columnLengths rows = map length rows
Prelude> columnLengths [[1,2], [1,55], [4,7,8]]
[2,2,3]
Now that we have a list containing the lengths of the columns, we have to check whether they are all equal. The function nub in Data.List removes duplicates from a list.
let columnsLengthEqual = (==) 1 . length . nub . columnLengths
Or all together
let columnsLengthEqual = (==) 1 . length . nub . map length
Matrix respecting your criteria, are squared matrix then checking if the square of first 's row's length is equal to the number of element should be ok.
isSquaredMatrix xs#(h:_) = ((^2) . length $ h) == (length . concat $ xs)
isSquaredMatrix _ = True
But as it has been pointed out by hammar, this is incorrect since we can have positive outcome using wrong input.
# isSquaredMatrix [[1,2,3],[4,5],[6,7,8,9]]
True -- But this is false
#John,
we use # into pattern matching when we want to refer to the whole type at the same time we have break it down. An example should give you more insight,
Usually we can define an exhaustive function working on list using pattern matching as follow.
actOnList [] = -- do something when we encounter an empty list
actOnList (x:xs) = -- do something with h, and do another stuff with xs
For example,
actOnList [] = []
actOnList (x:xs) =
if (pred x)
then x:xs
else actOnList xs
Here my function consumme the list until a predicate is satisfied.
We can imagine skipUntilMeetAChar
skipUntilMeetAChar :: [Char] -> Char -> [Char]
skipUntilMeetAChar [] c = []
skipUntilMeetAChar (x:xs) c =
if (x==c)
then x:xs
else actOnList xs c
As you see when the char is met we'd like to return the list as it, not only the tail, then to do so we need to reconstruct our list using the head x and the tail xs. This can be overcome using #.
skipUntilMeetAChar :: String -> Char -> String
skipUntilMeetAChar [] c = []
skipUntilMeetAChar l#(x:xs) c =
if (x==c)
then l
else actOnList xs c
Now, regarding ($) operator, this is again some syntactic sugar.
As function application are left associative, this lead us to extensively use bracket to reorder the application of our function, as in the example below.
# f3 (f2 (f1 (f0 x)))
Then to avoid the pain of managing closing parentheses, dollars operator $ have been introduce and then our previous expression become.
# f3 $ f2 $ f1 $ f0 x
Which is definitely more readable and easiest to write.
Note that this operator is defined as follow.
($) :: (a -> b) -> a -> b
f $ x = f x
And I advise you to learn more about it consulting the following introduction material.

Resources