Bruno
01/16/2020, 10:41 AMinteract
function takes a function of type String->String
as its argument. The entire input from the standard input device is passed to this function as its argument, and the resulting string is output on the standard output device.
I got something like:
fun interact(f: (String) -> String): IO<Unit> = IO.fx {
f.apply { readLine() }
}
but now I am unsure how to proceed.Jannis
01/16/2020, 11:04 AMIO
, however the task itself is not specific to IO
.Egor Trutenko
01/16/2020, 11:30 AMBruno
01/16/2020, 11:31 AMEgor Trutenko
01/16/2020, 11:32 AMBruno
01/16/2020, 11:33 AMEgor Trutenko
01/16/2020, 11:40 AMinteract
doesEgor Trutenko
01/16/2020, 11:42 AMSequence<Char>
. So I assume you may create an IO
and somehow transform the operation of reading chars from java InputStream
to Sequence of chars and go from thereJannis
01/16/2020, 11:57 AMJannis
01/16/2020, 11:59 AMJannis
01/16/2020, 12:00 PMJannis
01/16/2020, 12:03 PMinteract (show . head)
will only output the first char of what ever has been read, but since the haskell version reads everything first with IO and the output is sequenced after that, the effect of reading has to be fully executed first before it can print.Jannis
01/16/2020, 12:09 PMfun interact(f: (String) -> String): IO<Unit> = IO.fx {
val line = effect { readLine() }.bind()
effect { println(f(line)) }.bind()
interact(f).bind()
}
pakoito
01/16/2020, 1:54 PMf
to the this
scope, it doesn't apply
the function in haskell terms. What you're looking for is f.invoke
, or just f(readLine())
Bruno
01/16/2020, 2:39 PMfun add(a: Int, b: Int): Int = a + b
fun main(args: Array<String>) {
val sc = Scanner(System.`in`)
val num1 = sc.nextInt()
val num2 = sc.nextInt()
val sum = add(num1, num2)
println(sum)
}
pakoito
01/16/2020, 2:59 PMsuspend fun main(args: Array<String>) = IO.fx {
val sc = Scanner(System.`in`)
val nextInt = effect { sc.nextInt() }
val added = IO.mapN(nextInt, nextInt) { a, b -> add(a, b) }.bind()
effect { println(added) }.bind()
}.run { suspended() }
pakoito
01/16/2020, 3:01 PMrun
comes from the stdlib
, and it binds this
to the caller inside the {}
block. It's equivalent to myIO.let { c: IO<Unit> -> c.suspended() }
Jannis
01/16/2020, 3:01 PMIO
is lazy, defers side-effects and is an immutable value. You can move it around (as seen with nextInt
) and compose it effortlessly. The same cannot be said for the non-io version of this program.Bruno
01/16/2020, 3:10 PMimport sun.management.snmp.jvminstr.JvmThreadInstanceEntryImpl.ThreadStateMap.Byte0.suspended
Bruno
01/16/2020, 3:11 PM"0.10.4-SNAPSHOT"
and
"0.10.5-SNAPSHOT"
Bruno
01/16/2020, 3:14 PMpakoito
01/16/2020, 3:14 PMfix()
.suspended() because it's a member of IO afaikpakoito
01/16/2020, 3:15 PMJannis
01/16/2020, 3:23 PMparMapN
is a bad decision because it might execute out of order. @pakoito is refering to Applicative.map
which you can get with IO.applicative().map
. There is a ticket for renaming it to mapN
but atm it is still called map
Bruno
01/20/2020, 10:09 AMBruno
01/20/2020, 10:10 AMBruno
01/20/2020, 10:13 AMBruno
01/20/2020, 10:13 AMimport <http://arrow.fx.IO|arrow.fx.IO>
import arrow.fx.extensions.fx
import <http://arrow.fx.extensions.io|arrow.fx.extensions.io>.applicative.applicative
import java.util.*
Jannis
01/20/2020, 10:16 AMIO.applicative().map(io1, io2) { (a, b) -> add(a, b) }
. The parameter passed to Applicative.map
is always a TupleN
which you can destructure, not multiple parameters