Scala 3. 将 Continuation monad 示例从 Haskell 改编为 Scala

问题描述 投票:0回答:1

学习 Scala 3 与 monadic 主题。

https://jsdw.me/posts/haskell-cont-monad/

遇到了 Continuation monad 的可理解分解

当我尝试将简单的代码引入 Scala 时

twoC = \out -> out 2
helloC = \out -> out "hello"
ret val = \out -> out val

inC `bind` fn = \out -> inC (\inCval -> (fn inCval) out)

fourC = twoC `bind` \two -> ret (two*2)

twoHelloC = twoC `bind` \two ->
              helloC `bind` \hello ->
                ret $ (show two)++hello

我可以

fourC(identity)
编译并运行良好。 但是
bind
中的
twoHelloC
s 抱怨 Int/String 类型不匹配。

我当前的绑定实现:


val twoCont: (Int => Int) => Int =
  out => out(2)

val helloCont: (String => String) => String =
  out => out("hello")

type Cont[X, R] = (X => R) => R

extension[A, FinalRes] (inCont: Cont[A, FinalRes]) {
  infix def bind[B](fn: A => Cont[B, FinalRes]): Cont[B, FinalRes] = {
    (out: B => FinalRes) => inCont(inContVal => (fn(inContVal))(out))
  }
}

val twoHelloCont: (String => String) => String =
  twoCont bind (two =>
    helloCont bind (hello =>  // here it is unhappy to see Cont[String, String]
      return_(two.toString + hello)
      )
    )

问题: 您将如何在 Scala 中实现中缀

bind
,以及为什么 Haskell 类型系统允许
twoHelloC
进行编译?我在这里想念什么?

谢谢

scala haskell types monads continuations
1个回答
1
投票

如果你对 Haskell 中推断出的类型有疑问,你可以随时在 ghci 中提问

:t ...

ghci> :t twoHelloC
twoHelloC :: ([Char] -> t) -> t
ghci> :t fourC
fourC :: (Integer -> t) -> t
ghci> :t bind
bind :: ((t1 -> t2) -> t3) -> (t1 -> t4 -> t2) -> t4 -> t3
ghci> :t ret
ret :: t1 -> (t1 -> t2) -> t2
ghci> :t helloC
helloC :: (String -> t) -> t
ghci> :t twoC
twoC :: (Integer -> t) -> t

在 Scala 中,你应该从普通方法开始。详细翻译是

def twoC[A](out: Int => A): A = out(2)
def helloC[A](out: String => A): A = out("hello")
def ret[A1, A2](`val`: A1): (A1 => A2) => A2 =
  (out: A1 => A2) => out(`val`)
def bind[A1, A2, A3, A4](inC: (A1 => A2) => A3)(fn: A1 => A4 => A2): A4 => A3 =
  (out: A4) => inC((inCval: A1) => fn(inCval)(out))
def fourC[A]: (Int => A) => A =
  bind[Int, A, A, Int => A](twoC[A])((two: Int) => ret[Int, A](two * 2))
def twoHelloC[A]: (String => A) => A =
  bind[Int, A, A, String => A](twoC[A])((two: Int) =>
    bind[String, A, A, String => A](helloC[A])((hello: String) =>
      ret[String, A](two.toString + hello)
    )
  )

可以缩短为

def twoC[A](out: Int => A): A = out(2)
def helloC[A](out: String => A): A = out("hello")
def ret[A1, A2](`val`: A1): (A1 => A2) => A2 = out => out(`val`)
def bind[A1, A2, A3, A4](inC: (A1 => A2) => A3)(fn: A1 => A4 => A2): A4 => A3 =
  out => inC(inCval => fn(inCval)(out))
def fourC[A]: (Int => A) => A = bind(twoC[A])(two => ret(two * 2))
def twoHelloC[A]: (String => A) => A =
  bind(twoC[A])(two =>
    bind(helloC[A])(hello =>
      ret(two.toString + hello)
    )
  )

现在您可以添加

extension
infix
Cont

是否清楚如何完成翻译?

© www.soinside.com 2019 - 2024. All rights reserved.