"Wrapping mutable Java stuff in Frege means that everything will end up in an ST monad, which is almost always IO. That means that using Java’s HashSet will force anything that uses that to be in the IO monad itself. So there goes purity and referential transparency, which are some of the best parts of Haskell in the first place."
[0] https://www.reddit.com/r/haskell/comments/3gr7y6/infoq_frege...
[1] http://taylor.fausak.me/2015/06/25/frege-a-jvm-haskell/
EDIT: formatting
This is a bit misleading though I think, as you can actually unwrap and ST unlike an IO - my most common use for ST is actually to use a mutable object in a case where it's inefficient to keep copying immutable (e.g.: large vector or matrix manipulations) - then when you're done the ST monad can be unwrapped and you get the final structure - the entire function remains pure but inside of it, there are calculations that rely on state - but no state enters or leaves the function per say. This would mean using a hash set would be out of the question _for passing around outside of an ST monad_ but you could actually use it internally within functions.
Yes, but this is what the author was saying: you end up writing your code in ST. Remeber, there is no (general) way to freeze a mutable collection that was passed and then use it as if it was immutable. There can be a dozen different threads be busy modifying it.
However, as immutable objects are becoming more mainstream even in Java, there will still plenty of opportunities to make polyglot JVM programs employing pure code. Just not with the JAVA collection classes.
-- int frob(int, char*)
foreign import ccall "frob"
frob :: Int -> CString -> IO Int
If you know such a function to be pure, you can use unsafePerformIO to tell the type system: refrob :: Int -> CString -> Int
refrob x y = unsafePerformIO (frob x y)
If you lie to the type system and tell it that an impure function is pure, then all bets are off.The different syntax should not be a big issue, as Haskell code that uses FFI targeting C is per se not portable.
Better yet, if you know it to be pure, you can give it an appropriate type and just use it in pure code, like:
pure native cos java.lang.Math.cos :: Double -> Double
which should be roughly equivalent to: foreign import jvm "java.lang.Math.cos" cos :: Double -> Double
except that no Haskell compiler that I know implements the "jvm" calling convention, for obvious reasons.In fact, all primitive operations, types and so on are defined this way in the Frege Prelude.
But it is also not as relevant as one might think.
Consider how many Haskell programs actually use mutable C data, or export functions that take a foreign ptr to some mutable stuff.
Why should this be generally different in Frege? Useful Java APIs will be wrapped and sanitized through Frege libraries, and that is it then.
You can go directly to Java, just like you can directly go to C in Haskell, but it turns out one rarely actually does this.
This might be the reason that haskell has not enjoyed nearly the adoption of Scala and Clojure.
[0] https://github.com/Frege/frege-native-gen/issues/14 [1] https://github.com/Frege/frege/wiki/Differences-between-Freg...
http://mmhelloworld.github.io/blog/2013/07/10/frege-hello-ja...