In Haskell, the following code prints "[1,2,3,4,5":
foo = take 10 $ show $ numbersFrom 1 where
numbersFrom start = start : numbersFrom (start + 1) -- could use [1..]
But in Frege, It throws OutOfMemoryError
with the following code:
foo = take 10 $ unpacked $ show $ numbersFrom 1 where
numbersFrom start = start : numbersFrom (start + 1)
Here the only difference is the unpacked
function which is necessary to convert from String
to [Char]
and FWIW, the unpacked
function is eager. Why can't the whole expression be lazy as in Haskell? Is it possible to achieve something similar to Haskell in Frege here?
I don't know Frege, but according to the language definition String
is java.lang.String
so you can't build infinitely long strings (the out of memory issue probably has nothing to do with unpack
being eager).
Because you know each element of numbersFrom 1
will be shown as at least 1 character then you can over-approximate the size of the list to show then unpack, then take the number of desired characters:
foo = take 10 $ unpacked $ show $ take 10 $ numbersFrom 1 where
numbersFrom start = start : numbersFrom (start + 1)
Or more generally:
n = 10 -- number of characters to show
m = 1 -- minimum (map (length . show) xs) for some type of xs
foo :: a -> [Char]
foo = take n . unpack . show . take ((n+m-1) `div` m) . someEnumeration
where
someEnumeration :: a -> [a]
someEnumeration = undefined
If your enumeration is expensive then you can start taking into account the number of commas, whitespace, etc and reduce the argument to the second take
, but you get the idea.
I haven’t used Frege, but it seems to me that if unpacked
is strict, then its argument ought not be an infinite list. Try unpacked $ take 10
instead of take 10 $ unpacked
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With