将Haskell monad直接翻译成Scala [英] Direct translation of Haskell monad into Scala
问题描述
鉴于快速代码示例
import Control.Monad
pre>
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
我该如何在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 theLJ
type because you end up working on another level - not on a type as with typeclasses, but on the instance of a type. So theLJ
case class constructor becomes the counterpart ofreturn
.这篇关于将Haskell monad直接翻译成Scala的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!