
Dear friends - I must have clicked "reply" instead of "reply all" so here is the reply haskell cafe would have received: Matthew Bromberg wrote:
Not only does your suggestion make more sense than what I was doing, but also it causes the 'matrices' to behave as expected, namely to have the side effects incorporated into their array values.
I can't say I fully understand why this is true. In both cases I was wrapping Rmatrix in a monad after every computation. The difference is that the array component had an additional monad wrapper around and now it doesn't. That is,
old case newtype Rmatrix = Rmatrix (Int, Int, IO(StorableArray Int CDouble))
new case newtype Rmatrix = Rmatrix (Int, Int, StorableArray Int CDouble)
In the old way, the additional IO wrapper forces an additional nesting of do loops for most processing.
This is the essential difference, but I think you haven't quite understood what it means. When you say
The difference is that the array component had an additional monad wrapper around and now it doesn't.
this is not correct. IO (StorableArray Int CDouble) is a monadic *value* itself, which represents an *action* which returns a storable array, and since you are filling in the slot in Rmatrix with the action (newListArray a l), this monadic value represents the action of creating a new array whenever the action is executed. Whereas (StorableArray Int CDouble) is the actual array itself. You could also use your old definition of Rmatrix but change the way it is created eg: listtoRmatrix r c es = do arr <- newListArray (0, r * c) es return (Rmatrix r c (return arr)) do r2 <- listtoRmatrix 3 2 [1, 1, 1, 1, 1, 1] -- the rest is old code and everything would work as expected, because in this case, the monadic action contained in Rmatrix just returns the array arr that was created in the execution of listtoRmatrix 3 2 [1, 1, 1, 1, 1, 1], because listtoRmatrix is the only place where the action of creating a new array, ie (newListArray (0, r * c) es) is actually executed. I think the subtlety is one of these things that's very difficult to understand at first, but once you've grasped the fact that in Haskell expressions can evaluate to actions which are themselves values, and which in turn can create new values when executed, it will hopefully become a lot clearer. Regards, Brian. -- Logic empowers the living and justifies the dead. But societal laws, and religious dogma, empower the dead, to destroy what's living. http://www.metamilk.com