将Haskell monad直接翻译成Scala [英] Direct translation of Haskell monad into Scala

查看:109
本文介绍了将Haskell monad直接翻译成Scala的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图学习如何在Scala中编写monad,遇到了一些麻烦



鉴于快速代码示例

  import Control.Monad 

newtype LJ a = LJ {session :: a}

实例Monad LJ其中
返回s = LJ s
(>> =)mf = f(session m)

实例Functor LJ其中
fmap fm = LJ。 f $ session m

type SimpleLJ = LJ String

auth :: String - >字符串 - > SimpleLJ
auth = undefined

readFeed :: String - > SimpleLJ
readFeed = undefined

closeFeed :: String - > SimpleLJ
closeFeed = undefined

proceed = auth123456>> = readFeed>>> = closeFeed
pre>

我该如何在Scala(而不是scalaz)中编写相同的相同的东西?据我了解,在scala中实现map / flatMap方法就足够了,但这里返回的是什么?如何在 for 语句中使用没有自由变量的绑定?

解决方案

我相信应该回答你的问题。它并不完全是直接的,因为它不利用在Scala中以模式形式存在的类型类型,因为在目前的情况下,它只会在没有真正原因的情况下过于复杂。

  case class LJ [A](session:A){
//将其视为Haskell的fmap
def map [B](f:A => B):LJ [B] =
LJ(f(session))
//将其视为Haskell的>> =
def flatMap [B](f :A => LJ [B]):LJ [B] =
f(会话)
}

类型SimpleLJ = LJ [字符串]

def auth(a:String,b:String):SimpleLJ = ???

def readFeed(a:String):SimpleLJ = ???

close close(a:String):SimpleLJ = ???

def proceed:SimpleLJ =
auth(123,456)。flatMap(readFeed).flatMap(closeFeed)

//同上但是使用for-comprehension,它是
//用来替代Haskell的do--block
def proceed2:SimpleLJ =
for {
a < - auth( 123,456)
b < - readFeed(a)
c < - closeFeed(b)
}
收益c

该解决方案演示了一种经典的面向对象的方法。使用这种方法,你不能在 LJ 类型中封装 return 函数,因为你最终在另一个级别上工作 - 不是与类型类型相同,而是类型实例。因此, LJ case类构造函数成为 return 的对应元素。


Trying to learn how to program monads in Scala, got some troubles

Given the quick code sample

import Control.Monad

newtype LJ a = LJ { session :: a }

instance Monad LJ where
  return s = LJ s
  (>>=) m f = f ( session m )

instance Functor LJ where
  fmap f m = LJ . f $ session m

type SimpleLJ = LJ String

auth :: String -> String -> SimpleLJ
auth = undefined

readFeed :: String -> SimpleLJ
readFeed = undefined

closeFeed :: String -> SimpleLJ
closeFeed = undefined

proceed = auth "123" "456" >>= readFeed >>= closeFeed

how do I write the same thing in Scala (not scalaz)? As far as I learned, it's enough to implement map/flatMap methods in scala, but what is return here? And how to do binding without free variables in for statement?

解决方案

Here's an almost direct translation, which I believe should answer your question. It's not completely direct because it doesn't utilize typeclasses which are present in form of a pattern in Scala, because in the current case it would have only overcomplicated things without a real reason.

case class LJ[A]( session : A ) {
  // See it as Haskell's "fmap"
  def map[B]( f : A => B ) : LJ[B] = 
    LJ( f( session ) )
  // See it as Haskell's ">>="
  def flatMap[B]( f : A => LJ[B] ) : LJ[B] =
    f( session )
}

type SimpleLJ = LJ[String]

def auth( a : String, b : String ) : SimpleLJ = ???

def readFeed( a : String ) : SimpleLJ = ???

def closeFeed( a : String ) : SimpleLJ = ???

def proceed : SimpleLJ = 
  auth("123", "456").flatMap(readFeed).flatMap(closeFeed)

// Same as above but using a for-comprehension, which is 
// used as a replacement for Haskell's "do"-block
def proceed2 : SimpleLJ = 
  for {
    a <- auth("123", "456")
    b <- readFeed(a)
    c <- closeFeed(b)
  } 
  yield c

This solution demonstrates a classical object-oriented approach. With this approach you can't have the return function encapsulated in the LJ type because you end up working on another level - not on a type as with typeclasses, but on the instance of a type. So the LJ case class constructor becomes the counterpart of return.

这篇关于将Haskell monad直接翻译成Scala的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆