Code Monkey home page Code Monkey logo

Comments (3)

Hzqi avatar Hzqi commented on May 23, 2024

And same kind of code in Haskell, it works fine :

newtype Req = Req String deriving Show              
data Res a = SkipRes | NonRes | SomeRes [a] deriving Show 

instance Monoid (Res a) where
    mempty = NonRes
    SkipRes `mappend` _ = SkipRes
    _ `mappend` SkipRes = SkipRes
    NonRes `mappend` NonRes = NonRes
    NonRes `mappend` SomeRes a = SomeRes a
    SomeRes a `mappend` NonRes = SomeRes a
    SomeRes a `mappend` SomeRes b = SomeRes $ a ++ b
    mconcat = foldl1 mappend

instance Semigroup (Res a) where
    (<>) = mappend

newtype AbstractAction a = AbstractAction {runAbstractAction :: Req -> (a, Req)}

instance Monad AbstractAction where
    return a = AbstractAction $ \r -> (a,r)
    m >>= f = AbstractAction $ \r -> 
        let (a,r1) = runAbstractAction m r in
            runAbstractAction (f a) r1

instance Applicative AbstractAction where
    pure = return 
    (<*>) = ap

instance Functor AbstractAction where
    fmap = liftM

type Action a = AbstractAction (Res a)

action :: (Req -> (Res a, Req)) -> Action a
action = AbstractAction

runAction :: Action a -> (Req -> (Res a,Req))
runAction = runAbstractAction

first :: Action String
first = action f
    where 
        f r@(Req []) = (NonRes, Req " with 1 ")
        f r@(Req "skip") = (SkipRes, Req " with 1 ")
        f r@(Req as) = (SomeRes ["not empty req"], Req " with 1 ")

second :: Action String
second = action $ \(Req s) -> 
    let nr = Req $ s ++ " with 2" in
        (SomeRes $ ["get req:" ++ s], nr)

three :: Action String
three = do
    f <- first             -- f: Res String
    s <- second      -- s: Res String
    return $ f <> s  -- works ok,

from scalaz.

xuwei-k avatar xuwei-k commented on May 23, 2024

This is not a bug because Scala type is not equivalent to Haskell newtype.
I think you should create case class AbstractAction[A]

-  type AbstractAction[A] = Req => (A, Req)
+  case class AbstractAction[A](run: Req => (A, Req))
 
   implicit val monad = new Monad[AbstractAction] {
-    override def point[A](a: => A): AbstractAction[A] = r => (a, r)
+    override def point[A](a: => A): AbstractAction[A] = AbstractAction(r => (a, r))
 
-    override def bind[A, B](fa: AbstractAction[A])(f: A => AbstractAction[B]): AbstractAction[B] = (r:Req) => {
-      val (a,r1) = fa(r)
-      f(a)(r1)
-    }
+    override def bind[A, B](fa: AbstractAction[A])(f: A => AbstractAction[B]): AbstractAction[B] = AbstractAction((r:Req) => {
+      val (a,r1) = fa.run(r)
+      f(a).run(r1)
+    })
   }
 
   type Action[A] = AbstractAction[Res[A]]
 
-  def first = { (r: Req) =>
+  def first = AbstractAction{ (r: Req) =>
     if (r.value.isEmpty) (NonRes, Req(" with 1 "))
     else if (r.value == "skip") (SkipRes, Req(" with 1 "))
     else (SomeRes(List("not empty req")), Req(" with 1 "))
   }
 
-  def second = (r:Req) => (SomeRes(List("get req:"+r.value)), Req(r.value + " with 2 "))
+  def second = AbstractAction((r:Req) => (SomeRes(List("get req:"+r.value)), Req(r.value + " with 2 ")))
import scalaz._, Scalaz._

sealed case class Req(value:String) //stand for request
sealed trait Res[+A] { self => //stand for response
   def <>[B>:A](f2: Res[B]):Res[B] = (self,f2) match {
      case (SkipRes,_) => SkipRes
      case (_,SkipRes) => SkipRes
      case (NonRes,NonRes) => NonRes
      case (NonRes,a@SomeRes(_)) => a
      case (a@SomeRes(_),NonRes) => a
      case (SomeRes(a),SomeRes(b)) => SomeRes(a ++ b)
    }
  }
case class SomeRes[+A](value:List[A]) extends Res[A]
case object NonRes extends Res[Nothing]
case object SkipRes extends Res[Nothing]

object Main {

  case class AbstractAction[A](run: Req => (A, Req))

  implicit val monad = new Monad[AbstractAction] {
    override def point[A](a: => A): AbstractAction[A] = AbstractAction(r => (a, r))

    override def bind[A, B](fa: AbstractAction[A])(f: A => AbstractAction[B]): AbstractAction[B] = AbstractAction((r:Req) => {
      val (a,r1) = fa.run(r)
      f(a).run(r1)
    })
  }

  type Action[A] = AbstractAction[Res[A]]

  def first = AbstractAction{ (r: Req) =>
    if (r.value.isEmpty) (NonRes, Req(" with 1 "))
    else if (r.value == "skip") (SkipRes, Req(" with 1 "))
    else (SomeRes(List("not empty req")), Req(" with 1 "))
  }

  def second = AbstractAction((r:Req) => (SomeRes(List("get req:"+r.value)), Req(r.value + " with 2 ")))

  def three:Action[String] = for {
    f <- first
    s <- second
  } yield {f <> s} 

}

from scalaz.

Hzqi avatar Hzqi commented on May 23, 2024

It works, thx
By the way, it's that means I should use case class instead of type when I define something like Monad ?

from scalaz.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.