I've created a:
newType Board = Board (Array (Int, Int) Life)
, where
data Life = Alive|Dead
Im trying to make a function to save the board to a String by pattern matching:
showBoard:: Config -> String
showBoard Board(array ((0, 0), (w, h)) [(a:as)]) = *code*
But this only gives me "Parse error in pattern: array". I cant see what's wrong?
You can only pattern-match on data constructors. array is not a data constructor; it is a regular function that internal uses the Array data constructor(s) to create and return an Array value. The internal details
of an Array are not exposed, preventing you from pattern-matching on them.
Instead, you need use the functions provided for looking at an Array value. These can be composed with a function that does take arguments you can pattern match on.
-- bounds :: Array i e -> (i, i)
-- elems :: Array i e -> [e]
showConfig :: Board -> String
showConfig (Board arr) = showConfig' (bounds arr) (elems arr)
where showConfig' :: ((Int,Int),(Int,Int)) -> [Life] -> String
showConfig' ((0,0),(w,h)) (a:as) = ...
If you modify your Board type to
newtype Board = Board { getArray :: Array (Int, Int) Life }
you can rewrite showConfig in an applicative style:
showConfig = (showConfig' <$> boards <*> elems) . getArray
where showConfig' ((0,0),(w,h)) (a:as) = ...
Related
I need to write a function that takes a list of a and returns IO (IOArray Int a)
listToArray :: [a] -> IO (IOArray Int a)
I need some help to get started with IO arrays. I create a new one by newListArray but then it seems that I have to commit to a specific type and my function needs to work with any type a.
Thanks for the help!
If you want to work with any type you can take a look at this type signature
newListArray :: (MArray a e m, Ix i) => (i, i) -> [e] -> m (a i e)
where the m is IO, a is IOArray and i is Int.
This one requires start and end index of the array. You can see in detail here: http://hackage.haskell.org/package/array-0.5.4.0/docs/Data-Array-MArray.html#v:newListArray
I have tried this code in Haskell :
array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
squares = array (1,100) [(i, i*i) | i <- [1..100]]
But when i run that Code i get this message by GHCi:
The type signature for array lacks an accompanying binding
(The type signature must be given where array is declared)
What exactly is meant with accompanying binding and how to fix that?
Because you define a type signature for array, not squares (array is a library function, you cannot redefine it, you can of course write your own). Now the compiler thinks you aim to define your own array and says: "Got that, but where is your function definition?" it thus lacks a binding (implementation so to speak).
The binding is thus its implementation (here squares = array (1,100) [(i, i*i) | i <- [1..100]]). Furthermore between brackets the compiler also says that you cannot define the function where you want, it must be in the file where the function signature is (the signature is where you define its type so :: (Ix a) => (a,a) -> [(a,b)] -> Array a b).
Given you meant to give a signature to squares, the type signature is too broad. The most generic type signature is:
squares :: (Enum e, Num e, Ix e) => Array e e
squares = array (1,100) [(i, i*i) | i <- [1..100]]
i have an array of real values like [|1.2, 3.4, 5.3, 2.5|]
fun max_arr arr = foldl Real.max (sub (arr, 0)) arr;
works fine to find the max value 5.3 .
Then i would expect something like
fun max_arri arr = foldli (Real.max(sub (arr, 0))) arr;
to successfully return the location of max value 2.but it doesn't work.
(Error: unbound variable or constructor: max_arri)
I went through everything I could find online but the documentation about sml seems small...
according to the manual they both take the same data. so what would i need to change?
foldli f init arr
foldl f init arr
also i dont want to use lists because i change the data alot
They do not take the same input.
foldl :: ( 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
foldli :: (int * 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
As we can see from the types, the difference is that foldli takes a function that also takes an integer -- the index of the element.
The return type of the two functions are both 'b, so foldli does not return the index. Rather, this expression:
foldli (fn (i, a, b) => f (a, b)) init arr
Is the exact equivalent of this expression:
foldl f init arr
Now, if we want to return the index of an element, we need the 'b in the type of foldli to become int. However, finding the maximum relies on comparison of elements, so we also need the current maximum, just like in your max_arr function. The obvious solution is to use a tuple. 'b now becomes (real * int).
(* cElem = current element
* cI = current index
*)
fun fmax (i, elem : real, (cElem, cI)) =
if cElem > elem
then (cElem, cI)
else (elem, i)
fun max_arri arr = foldli fmax (sub (arr, 0), 0) arr
Of course, this is not the type we want our max_arri to return - we only want the index. The loose helper function isn't very nice either, but it's a bit long to have as a lambda. Instead, we wrap it all in a local:
local
fun fmax (i, elem : real, (cElem, cI)) =
if cElem > elem
then (cElem, cI)
else (elem, i)
fun max_arri' arr = foldli fmax (sub (arr, 0), 0) arr
in
fun max_arri arr = let val (_, i) = max_arri' arr
in i end
end
In ML I have an array of chars! I am trying to find an array function in order to give the function the char #"T" and returns me the position of this element in array. I tried the find function and it doesn't work like that!
findi from the Array structure will do what you want. For an array of type 'a array, findi takes a (int * 'a) -> bool and a 'a array and returns an (int * 'a) option. So if you want to take a character and just return the character's position, you just need figure out the appropriate arguments to pass to findi and the appropriate way to interpret the result.
So for instance:
- fun findPos char = (Option.map (fn (i,_) => i)) o (Array.findi (fn (_,c) => c = char));
stdIn:2.65 Warning: calling polyEqual
val findPos = fn : ''a -> ''a array -> int option
- findPos #"c" (Array.fromList (explode "abcdef"));
val it = SOME 2 : int option
- findPos #"z" (Array.fromList (explode "abcdef"));
val it = NONE : int option
I see that I can map a function over mutable arrays with mapArray, but there doesn't seem to be something like mapM (and mapM_). mapArray won't let me print its elements, for example:
import Data.Array.Storable
arr <- newArray (1,10) 42 :: IO -- answer to Life, Universe and Everything
x <- readLn :: IO Int
mapArray (putStrLn.show) arr -- <== this doesn't work!
The result will be:
No instances for (MArray StorableArray Int m,
MArray StorableArray (IO ()) m)
arising from a use of `mapArray' at <interactive>:1:0-27
Possible fix:
add an instance declaration for
(MArray StorableArray Int m, MArray StorableArray (IO ()) m)
In the expression: mapArray (putStrLn . show) arr
In the definition of `it': it = mapArray (putStrLn . show) arr
Is there something like that in Haskell (or in GHC even if not standard Haskell)?
Also, I found no foldr/foldl functions for arrays (mutable or not). Do they exist?
Thanks a lot!
Import the module Data.Traversable. It defines a typeclass for just what you want with instances already defined for array and all sorts of things. It has generalized versions of sequence and mapM, plus some even more general functions that you probably won't bother with very often.
Just a simple
import Data.Traversable as T
T.mapM doIOStuff arr
works fine.
Perhaps use one of the other array libraries, if you're doing a lot of mutation? Like uvector?
Otherwise,
forM_ [1..n] \$ \i ->. unsafeWrite x i
should be fine.
For the example of printing all the elements: you can use "mapM_ print . elems".
But it sounds like you want to create a new array where each value is the result of a monadic action of the previous one? In that case:
arrayMapM :: (Monad m, Ix i) => (a -> m b) -> Array i a -> m (Array i b)
arrayMapM func src =
liftM (listArray (bounds src)) . mapM func . elems $ src