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