As I've been learning haskell I've enjoyed the pure parts but now I am stumbling through the monadic and IO parts and probably experiencing what some people find truly infuriating about the language. I solving a project euler problem and I simple want a mutable array because I have to update elements frequently by index. I tried Vectors but couldn't get them working so I tried Data.Array.IO. I can read and write elements fine but I can't display the array in terminal the way I want. So far I have this.
test = do
arr <- newArray (1,10) 37 :: IO (IOArray Int Int)
a <- readArray arr 1
writeArray arr 1 64
b <- readArray arr 1
dispArray arr
return ()
dispArray arr = do
(a,b) <- getBounds arr
printf "["
dispArray' arr a
printf "]\n"
where dispArray' arr i = do
(a,b) <- getBounds arr
if i < a || i > b
then return ()
else do
v <- readArray arr i
print v
dispArray' arr (i+1)
The ouput of this as you would expect is this:
[64
37
37
37
37
37
37
37
37
37
]
But this is inconvenient and I want this [64,37,37,37.... like this. I've seen functions that are something like toList, but I don't want this. I don't want to convert to a list everytime I display. So I figured I would need to use printf. So I replaced print v with printf " %s," (show v). But this doesn't compile. I don't know why. I thought it would because print :: Show a => a -> IO () and show :: Show a => a -> String so why wouldn't it work because %s signifies a string? So I then put to calls next to each other. To see if printf would even work.
printf " %s," "hello"
print v
Which compiles and displays:
[ hello,64
hello,37
hello,37
hello,37
hello,37
hello,37
hello,37
hello,37
hello,37
hello,37
]
Why can I not use show v? Why is haskell IO so infuriating to beginners?
This is an interesting type-checking puzzle.
The error message that the call to printf produces is
Could not deduce (PrintfType (m a0))
arising from the ambiguity check for `dispArray'
The phrases Could not deduce and ambiguity typically hint at the fact that GHC has
insufficient type information in order to conclude how this program should be typed. This might be a real type error, but it's also possible that it can be fixed simply by providing more type information (and this is the case here).
The culprit here is really printf, combined with the flexibility of the mutable array interface, and not so much Haskell's IO system. The type of printf is an ingenious hack, but still a hack. In order to know a flexible number of parameters of various types that depend on just the format string, printf has a type that isn't very safe nor very informative:
printf :: PrintfType r => String -> r
So all we really know for sure is that the first argument is of type String. The rest can be any type r that is in the type class PrintfType.
The details of the instances do not matter. What's interesting is that show produces a String, and if we apply printf to a format string and then a show-produced second string, we are still left with a rather uninformative type:
> :t printf "%s," (show 2)
printf "%s," (show 2) :: PrintfType t => t
In particular, there's no indication here that the result is to be in the IO monad.
This normally wouldn't be a problem, if GHC could conclude from the context that you're in IO. But within dispArray', the only other functions you are calling are readArray, getBounds, return (and dispArray' recursively). None of these functions specifies that it lives in IO either. In particular, all of the array functions are overloaded over the monad, for example:
getBounds :: (Ix i, MArray a e m) => a i e -> m (i, i)
(And indeed, getBounds could, for example, also work in an ST monad context.) So there's simply nothing in dispArray' that determines that you live in IO. And that in turn means that GHC cannot resolve the type of printf.
As I said, it's a consequence of the desired flexibility of printf that printf itself cannot provide this information, and it has to be available externally.
The solution is easy enough. As suggested in one of the comments, it is sufficient to annotate the result type of the call to printf:
printf "%s," (show v) :: IO ()
As you're using printf anyway (and if you're actually only interested in arrays of decimal numbers), you could also use:
printf "%d," v :: IO ()
It would also sufficient (but less clear to the reader) to give a type signature for anything else within the definition of dispArray' so that it fixes the return type to be IO (). For example, you could annotate the return () in the then-branch of the if expression:
return () :: IO ()
The incantation you want is:
putStr (show v)
That prints out v without a newline.
Related
I'm trying to initialize an array with equal spacing between 0 and 1 in fortran.
My code is :
program test
double precision :: h
double precision, dimension(:), allocatable :: x
h = 1./11
if(.not. allocated(x)) allocate(x(10))
x(1:10) = [h:(1-h):h] (*)
end program
The error I am given is "The highest data type rank permitted is INTEGER(KIND=8)" at the stared line.
I've tried to change it with
x(1:10) = h:(1-h):h
x = h:(1-h):h
x(1:10) = (/(h:(1-h):h)/)
and various other forms with no luck.
The syntax you're using is not valid Fortran and implied DO loops can't have non-integer bounds. You want something like this:
x = h * real([(i,i=1,size(x))],kind(h))
For more information, look up "array constructors" in the standard or a textbook.
Don't use (1:10) on the left side - see https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this
This expression
[h:(1-h):h]
is, from a Fortran point of view, broken. It looks a bit like an array slice, but that would require integers, not reals, and ( and ) rather than the [ and ]. And it looks a bit like an array constructor, for which [ and ] are correct, but h:(1-h):h isn't.
Try this
x = REAL([(ix,ix=1,10)],real64)/11
(having declared ix to be an integer). The expression (ix,ix=1,10) is an implied do-loop and, inside the [ and ] produces an array with integers from 1 to 10. I trust the rest is obvious.
Incidentally, since the lhs of my suggested replacement is the whole of x you don't actually need to explicitly allocate it, Fortran will automatically do that for you. This is one of the differences between a whole array section, such as your x(1:10) and the whole array, x.
And if that doesn't produce the results you want let us know.
What is the fastest way to flatten an array of arrays in ocaml? Note that I mean arrays, and not lists.
I'd like to do this linearly, with the lowest coefficients possible.
OCaml Standard Library is rather deficient and requires you to implement so many things from scratch. That's why we have extended libraries like Batteries and Core. I would suggest you to use them, so that you will not face such problems.
Still, for the sake of completeness, let's try to implement our own solution, and then compare it with a proposed fun xxs -> Array.(concat (to_list xxs)) solution.
In the implementation we have few small problems. First of all in order to construct an array we need to provide a value for each cell. We can't just create an uninitialized array, this will break a type system. We can, of course use Obj module, but this is rather ugly. Another problem, is that the input array can be empty, so we need to handle this case somehow. We can, of course, just raise an exception, but I prefer to make my functions total. It is not obvious though, how to create an empty array, but it is not impossible:
let empty () = Array.init 0 (fun _ -> assert false)
This is a function that will create an empty polymorphic array. We use a bottom value (a value that is an inhabitant of every type), denoted as assert false. This is typesafe and neat.
Next is how to create an array, without having a default value. We can, write a very complex code, that will use Array.init and translate ith index to j'th index of n'th array. But this is tedious, error prone and quite ineffective. Another approach would be to find a first value in the input array and use it as a default. Here comes another problem, as in Standard Library we don't have an Array.find function. Sic. It's a shame that in 21th century we need to write an Array.find function, but this is how life is made. Again, use Core (or Core_kernel) library or Batteries. There're lots of excellent libraries in OCaml community available via opam. But back to our problem, since we don't have a find function we will use our own custom solution. We can use fold_left, but it will traverse the whole array, albeit we need to find only the first element. There is a solution, we can use exceptions, for non-local exits. Don't be afraid, this is idiomatic in OCaml. Also raising and catching an exception in OCaml is very fast. Other than non local exit, we also need to send the value, that we've found. We can use a reference cell as a communication channel. But this is rather ugly, and we will use the exception itself to bear the value for us. Since we don't know the type of an element in advance, we will use two modern features of OCaml language. Local abstract types and local modules. So let's go for the implementation:
let array_concat (type t) xxs =
let module Search = struct exception Done of t end in
try
Array.iter (fun xs ->
if Array.length xs <> 0
then raise_notrace (Search.Done xs.(0))) xxs;
empty ()
with Search.Done default ->
let len =
Array.fold_left (fun n xs -> n + Array.length xs) 0 xxs in
let ys = Array.make len default in
let _ : int = Array.fold_left (fun i xs ->
let len = Array.length xs in
Array.blit xs 0 ys i len;
i+len) 0 xxs in
ys
Now, the interesting part. Benchmarking! Let's use a proposed solution for comparison:
let default_concat xxs = Array.concat (Array.to_list xxs)
Here goes our testing harness:
let random_array =
Random.init 42;
let max = 100000 in
Array.init 1000 (fun _ -> Array.init (Random.int max) (fun i -> i))
let test name f =
Gc.major ();
let t0 = Sys.time () in
let xs = f random_array in
let t1 = Sys.time () in
let n = Array.length xs in
printf "%s: %g sec (%d bytes)\n%!" name (t1 -. t0) n
let () =
test "custom " array_concat;
test "default" default_concat
And... the results:
$ ./array_concat.native
custom : 0.38 sec (49203647 bytes)
default: 0.20 sec (49203647 bytes)
They don't surprise me, by the way. Our solution is two times slower than the standard library. The moral of this story is:
Always benchmark before optimizing
Use extended libraries (core, batteries, containers, ...)
Update (concatenating arrays using Base)
With the base library, we can concatenate arrays easily,
let concat_base = Array.concat_map ~f:ident
And here's our benchmark:
./example.native
custom : 0.524071 sec (49203647 bytes)
default: 0.308085 sec (49203647 bytes)
base : 0.201688 sec (49203647 bytes)
So now the base implementation is the fastest and the smallest.
I've only been learning Fortran 77 (and its syntax) the last few days, and tried finding answers throughout the site and textbooks already and come up still confused, so I'd appreciate any help. I'm sorry if the formatting on this post is off; this is my first post, and I'm crunched for time.
I'm creating a program to multiply matrices. I want to create a subroutine or a function that will take two matrices as inputs (two 2x2 arrays), and return the multiplied matrix (one 2x2 array). I can't figure out how to get either a subroutine or a function to return an array of fixed size, or how to use the array once it's returned.
I tried using a function, which compiled on its own. But when I tried calling the function from my main program, I couldn't call it on its own:
MATMULT(MAT0, MAT0, MAT0)
1
Error: Unclassifiable statement at (1)
or assign it to another variable (I tried different REALs and arrays):
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Error: Return type mismatch of function 'matmult' at (1) (INTEGER(4)/REAL(4))
MATRIX1.f:26.22:
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Warning: Type mismatch in argument 'x' at (1); passed INTEGER(4) to REAL(4)
BLAH = MATMULT(MAT0, MAT0, MAT0)
1
Warning: Rank mismatch in argument 'x' at (1) (scalar and rank-2)
Since arrays are passed by reference, I'm really not sure what the function is returning, so how can I use the output matrix, if that is indeed the function's output?
I also tried using a subroutine, but (in addition to still not knowing what it's returning or where) then I get a "Two main PROGRAMs" error - so the compiler isn't differentiating between the main program and the subroutine. This might be a problem with my syntax on subroutines? I tried a few different things, but here's my most recent iteration of the code (I'm just trying to get the array-passing to work, so there's not actual matrix multiplication in here yet):
PROGRAM MATRIX1
INTEGER N
REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
REAL BLAH
PRINT *, " ENTER THE VALUE OF A: "
READ *, A
PRINT *, " ENTER THE VALUE OF B: "
READ *, B
PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
READ *, N
C Creates the initial matrix
MAT0(1,1) = 1.0 - A
MAT0(1,2) = A
MAT0(2,1) = B
MAT0(2,2) = 1.0 - B
PRINT *, "M = ", MAT0
CALL MATMULT(MAT0, MAT0, MAT0)
PRINT *, "FINAL "
STOP
END PROGRAM
REAL SUBBROUTINE MATMULT(X, Y, Z)
END SUBROUTINE
Or (edited to add some of the recommended changes) with a function:
PROGRAM MATRIX1
INTEGER N
REAL A, B, MAT0(2,2), MATF(2,2), X(2,2), Y(2,2), Z(2,2)
REAL MATMULT(2,2)
PRINT *, " ENTER THE VALUE OF A: "
READ *, A
PRINT *, " ENTER THE VALUE OF B: "
READ *, B
PRINT *, " ENTER THE NUMBER OF MULTIPLICATIONS: "
READ *, N
C Creates the initial matrix
MAT0(1,1) = 1.0 - A
MAT0(1,2) = A
MAT0(2,1) = B
MAT0(2,2) = 1.0 - B
PRINT *, "M = ", MAT0
Z = MATMULT(X, Y)
STOP
END PROGRAM
FUNCTION MATMULT(X, Y)
REAL X(2,2), Y(2,2), Z(2,2), MATMULT(2,2)
RETURN
END
I'm still getting errors:
Z = MATMULT(X, Y)
1
Warning: Legacy Extension: REAL array index at (1)
MATRIX1.f:28.19:
Z = MATMULT(X, Y)
1
Error: Array index at (1) is an array of rank 2
In this era there is no reason for use FORTRAN 77. Fortran 90/95/2003 is easier to use, more powerful, and better assists the programer in finding mistakes. gfortran is an excellent open-source compiler.
Here is an example in Fortran 95 of a similar program/function: a function that implements a vector-cross product. The example shows the function and program in the same file (there are other approaches) with the function receiving two vectors and returning one vector. Example: Computing the cross product of two vectors in Fortran 90
You mention several problems in your question. Certainly your work will be enhanced using more recent Fortran dialects, as given in the answers by M. S. B. and Ilmirus. And you really should be using implicit none (even for Fortran 77 a lot of compilers support that - and lower case - as an extension).
Coming to the conceptual part, I must say that you need to continue your learning. However, if you want a function which returns the matrix product then you will have something like
function matmult(x, y)
real x(2,2), z(2,2), matmult(2,2)
... calculation of matmult
end function matmult
Followed by
z = matmult(x,y)
in the main program, where z is real z(2,2), rather than the scalar blah you have in your example, and is your result.
Coming to your subroutine, there are indeed problems: real subroutine matmult(x,y,z) requires not the real. Then calling this with call matmult(mat0, mat0, mat0) where you intend to update mat0 with a result is asking for aliasing problems. call matmult(x,y,z) will "store the result" where the subroutine calculations put it. Using intent as given by Ilmirus is a good guide to the behaviour desired by the programmer.
Finally, if you just want to get the result of multiplying A and B as matrices and storing in C: use C = matmul(A,B) with a later-than-F77 compiler.
However, in Fortran 77 one doesn't return array results, so the subroutine approach is the one to go for. In response to your edit:
REAL MATMULT(2,2)
is declaring matmult an array, not a function, so references to matmult(X,Y) give rise to your error.
There are two ways to do this:
1) Subroutine. Declare a subroutine like you did. However, specify input and output parameters:
REAL, INTENT(IN) :: X(2,2), Y(2,2)
REAL, INTENT(OUT) :: Z(2,2)
and call the subroutine using call keyword: CALL MATMULT
2) Function. Also specify input parameter, but now return value of the function:
! Insert calculation
MALMULT = ...
Don't forget to declare it in proper way: FUNCTION MATMULT(x,Y)
Call it: Z = MATMULT(X,Y)
With the question Listing all the contents of a directory by breadth-first order results in low efficiencyI learned that the low efficiency is due to a strange behavior of the recursive monad functions.
Try
sequence $ map return [1..]::[[Int]]
sequence $ map return [1..]::Maybe [Int]
and ghci will fall into an endless calculation.
If we rewrite the sequence function in a more readable form like follows:
sequence' [] = return []
sequence' (m:ms) = do {x<-m; xs<-sequence' ms; return (x:xs)}
and try:
sequence' $ map return [1..]::[[Int]]
sequence' $ map return [1..]::Maybe [Int]
we get the same situation, an endless loop.
Try a finite list
sequence' $ map return [1..]::Maybe [Int]
it will spring out the expected result Just [1,2,3,4..] after a long time waiting.
From what we tried,we can come to the conclusion that although the definition of sequence' seems to be lazy, it is strict and has to make out all the numbers before the result of sequence' can be printed.
Not only just sequence', if we define a function
iterateM:: Monad m => (a -> m a) -> a -> m [a]
iterateM f x = (f x) >>= iterateM0 f >>= return.(x:)
and try
iterateM (>>=(+1)) 0
then endless calculation occurs.
As we all know,the non-monadic iterate is defined just like the above iterateM, but why the iterate is lazy and iterateM is strict.
As we can see from above, both iterateM and sequence' are recursive monadic functions.Is there some thing strange with recursive monadic functions
The problem isn't the definition of sequence, it's the operation of the underlying monad. In particular, it's the strictness of the monad's >>= operation that determines the strictness of sequence.
For a sufficiently lazy monad, it's entirely possible to run sequence on an infinite list and consume the result incrementally. Consider:
Prelude> :m + Control.Monad.Identity
Prelude Control.Monad.Identity> runIdentity (sequence $ map return [1..] :: Identity [Int])
and the list will be printed (consumed) incrementally as desired.
It may be enlightening to try this with Control.Monad.State.Strict and Control.Monad.State.Lazy:
-- will print the list
Prelude Control.Monad.State.Lazy> evalState (sequence $ map return [1..] :: State () [Int]) ()
-- loops
Prelude Control.Monad.State.Strict> evalState (sequence $ map return [1..] :: State () [Int]) ()
In the IO monad, >>= is by definition strict, since this strictness is exactly the property necessary to enable reasoning about effect sequencing. I think #jberryman's answer is a good demonstration of what is meant by a "strict >>=". For IO and other monads with a strict >>=, each expression in the list must be evaluated before sequence can return. With an infinite list of expressions, this isn't possible.
You're not quite grokking the mechanics of bind:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Here's an implementation of sequence that only works on 3-length lists:
sequence3 (ma:mb:mc:[]) = ma >>= (\a-> mb >>= (\b-> mc >>= (\c-> return [a,b,c] )))
You see how we have to "run" each "monadic action" in the list before we can return the outer constructor (i.e. the outermost cons, or (:))? Try implementing it differently if you don't believe.
This is one reason monads are useful for IO: there is an implicit sequencing of effects when you bind two actions.
You also have to be careful about using the terms "lazy" and "strict". It's true with sequence that you must traverse the whole list before the final result can be wrapped, but the following works perfectly well:
Prelude Control.Monad> sequence3 [Just undefined, Just undefined, Nothing]
Nothing
Monadic sequence cannot in general work lazily on infinite lists. Consider its signature:
sequence :: Monad m => [m a] -> m [a]
It combines all monadic effects in its argument into a single effect. If you apply it to an infinite list, you'd need to combine an infinite number of effect into one. For some monads, it is possible, for some monads, it is not.
As an example, consider sequence specialized to Maybe, as you did in your example:
sequence :: [Maybe a] -> Maybe [a]
The result is Just ... iff all elements in the array are Just .... If any of the elements is Nothing then the result is Nothing. This means that unless you examine all elements of the input, you cannot tell if the result is Nothing or Just ....
The same applies for sequence specialized to []: sequence :: [[a]] -> [[a]]. If any of the elements of the argument is an empty list, the whole result is an empty list, like in sequence [[1],[2,3],[],[4]]. So in order to evaluate sequence on a list of lists, you have to examine all the elements to see what the result will look like.
On the other hand, sequence specialized to the Reader monad can process its argument lazily, because there is no real "effect" on Reader's monadic computation. If you define
inf :: Reader Int [Int]
inf = sequence $ map return [1..]
or perhaps
inf = sequence $ map (\x -> reader (* x)) [1..]
it will work lazily, as you can see by calling take 10 (runReader inf 3).
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