2

I try to get the word-count example from real-world Haskell running in Frege:

main _ = interact wordCount
    where wordCount input = show (length (lines input)) ++ "\n"

but I get

can't resolve `interact`

Is there a Frege-idiomatic way to do this?

Dierk
  • 1,308
  • 7
  • 13

1 Answers1

3

It is not in the standard library but you can define something like this:

import Data.List(intercalate)

interact :: (String -> String) -> IO ()
interact f = stdin.getLines >>= println . f . intercalate "\n"

Update (for the comment on Groovy's eachLine):

Frege has try, catch, finally and BufferedReader.getLine that we can use to create such a function:

eachLine :: Reader -> (String -> IO ()) -> IO ()
eachLine reader f = BufferedReader.new reader >>= go where
  go breader = forever (breader.getLine >>= f)
    `catch` (\(e :: EOFException) -> return ())
    `finally` breader.close

try, catch and finally are functions with the following types:

try :: (Applicative γ,Bind γ) => (α->γ β) -> α -> γ β
catch :: Exceptional β => ST γ α -> (β->ST γ α) -> ST γ α
finally :: IO α -> IO β -> IO α

And we can just use catch and finally without try as we have done in eachLine above. Please see this note from Frege source on when try is necessary.

Marimuthu Madasamy
  • 13,126
  • 4
  • 30
  • 52
  • 1
    Exactly. From the Java API, the most natural way is to get the input in terms of lines. Which is nice, because we need not deal with different end-of-line character sequences. Hence, the `interact` function tends to be somewhat unidiomatic in Frege. We'd need an IO action that delivers the input as a single long String. Otherwise we split the input in lines, concatenate it again to a String only to pass it to a function that most likely splits it into lines again. – Ingo Sep 12 '13 at 16:54
  • For larger files/input that we do not want to fully load into memory, it would be nice to read line by line and do something with it. What I have in mind is like Groovy's `reader.eachLine { line -> println line }` http://groovy.codehaus.org/groovy-jdk/java/io/Reader.html#eachLine(groovy.lang.Closure) A more functional candidate would be "transformLine". Needless to say that these methods properly close the underlying handles even in case of exceptions. – Dierk Sep 12 '13 at 20:33
  • Thanks, Marimuthu for the great eachLine example! – Dierk Sep 13 '13 at 08:57