Haskell Array Pattern in a function - arrays

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.

Related

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.

Vectorize an S4 class in R

I got some troubles defining array like classes in a way that they are fully typed (as far as that is possible in R).
My example: I want to define a class Avector, which should contain an arbitrary number of elements of the class A.
# Define the base class
setClass("A", representation(x = "numeric"))
# Some magic needed ????
setClass("Avector", ???)
# In the end one should be able to use it as follows:
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
X <- new("Avector", c(a1, a2))
I am aware that having a vector of objects is not possible in R. So I guess it will be stored in a kind of "typed" list.
I have found some solution, but I am not happy with it:
# Define the vectorized class
setClass(
"Avector",
representation(X = "list"),
valididty = function(.Object)) {
if (all(sapply(.Object#X, function(x) class(x) == "A")))
TRUE
else
"'Avector' must be a list of elements in the class 'A'"
}
)
# Define a method to subscript the elements inside of the vector
setMethod(
"[", signature(x = "Avector", i = "ANY", j = "ANY"),
function(x, i, j, ...) x#X[[i]]
)
# Test the class
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
avec <- new("Avector", X = list(a1, a2))
# Retrieve the element in index i
avec[i]
This method appears more like a hack to me. Is there a way to do this in a canonical way in R without doing this type checking and indexing method by hand?
Edit:
This should also hold, if the class A is not consisting of atomic slots. For example in the case that:
setClass("A", representation(x = "data.frame"))
I would be glad for help :)
Cheers,
Adrian
The answer depends somewhat on what you are trying to accomplish, and may or may not be possible in your use case. The way S4 is intended to work is that objects are supposed to be high-level to avoid excessive overheads.
Generally, it is necessary to have the slots be vectors. You can't define new atomic types from within R. So in your toy example instead of calling
avec <- new("Avector", X = list(a1, a2))
you call
avec <- new("A", x = c(1, 2))
This may necessitate other slots (which were previously vectors) becoming arrays, for example.
If you're desperate to have an atomic type, then you might be able to over-ride one of the existing types. I think the bit64 package does this, for example. Essentially what you do is make a new class that inherits from, say, numeric and then write lots of methods that supersede all the default ones for your new class.

F# Sort an Array with foldBack or fold.

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.

Matrix as Applicative functor, which is not Monad

I run into examples of Applicatives that are not Monads. I like the multi-dimensional array example but I did not get it completely.
Let's take a matrix M[A]. Could you show that M[A] is an Applicative but not a Monad with Scala code ? Do you have any "real-world" examples of using matrices as Applicatives ?
Something like M[T] <*> M[T => U] is applicative:
val A = [[1,2],[1,2]] //let's assume such imaginary syntax for arrays
val B = [[*2, *3], [*5, *2]]
A <*> B === [[2,6],[5,4]]
There may be more complex applicatives in signal processing for example. Using applicatives allows you to build one matrix of functions (each do N or less element-operations) and do only 1 matrix-operation instead of N.
Matrix is not a monoid by definition - you have to define "+" (concatenation) between matrixes for that (fold more precisely). And not every (even monoidal) matrix is a monad - you have to additionaly define fmap (not flatMap - just map in scala) to make it a Functor (endo-functor if it returns matrix). But by default Matrix isn't Functor/Monoid/Monad(Functor + Monoid).
About monadic matrixes. Matrix can be monoid: you may define dimension-bound concatenation for matrixes that are same sized along the orthogonal dimension. Dimension/size-independent concatenation will be something like:
val A = [[11,12],[21,22]]; val B = [[11,12,13],[21,22,23],[31,32,33]]
A + B === [[11,12,0,0,0], [21,22,0,0,0], [0,0,11,12,13],[0,0,21,22,23],[0,0,31,32,33]
Identity element will be []
So you can also build the monad (pseudocode again):
def flatMap[T, U](a: M[T])(f: T => M[U]) = {
val mapped = a.map(f)// M[M[U]] // map
def normalize(xn: Int, yn: Int) = ... // complete matrix with zeros to strict xn * yn size
a.map(normalize(a.max(_.xn), a.max(_.yn)))
.reduceHorizontal(_ concat _)
.reduceVertical(_ concat _) // flatten
}
val res = flatMap([[1,1],[2,1]], x => if(x == 1)[[2,2]] else [[3,3,3]])
res === [[2,2,0,2,2],[3,3,3,2,2]]
Unfortunately, you must have zero-element (or any default) for T (not only for monoid itself). It doesn't make T itself some kind of magma (because no defined binary operation for this set is required - only some const defined for T), but may create additional problems (depending on your challenges).

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

Resources