Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic function that accepts two monadic values and returns a single monadic value

I've the written the following Haskell function which accepts two monadic values and combine them into a single monadic value (it's just to illustrate the degree of genericity (or generic-ness) that Haskell type-system could support).

combine x y = do
  a <- x
  b <- y
  return (a, b)

and I tested it with three different monads:

main = do
  putStrLn $ show $ combine (Just 10) (Just 20)  -- Maybe a
  putStrLn $ show $ combine [100] [10, 20]       -- [] a
  a <- combine getLine getLine                   -- IO a
  putStrLn $ show a

And it works great as expected. Now, I want to know if Scala's type-system could allow me to write the above function without compromising the genericity. But I don't know Scala enough (though I wish to explore it). So could anyone help me convert this code into Scala?

like image 853
Nawaz Avatar asked Dec 18 '22 23:12

Nawaz


1 Answers

I think this is the equivalent:

import cats._
import cats.implicits._

def combine[T, F[_]: Monad](fa: F[T], fb: F[T]) = for {
    a <- fa
    b <- fb
  } yield (a, b)

Where Monad is from a library (cats or scalaz).

combine(Option(10), Option(20)) produces Some((10,20)) and combine(List(100), List(10, 20)) produces List((100,10), (100,20)).

EDIT: The above version is over-constrained, since it requires the two argument types to be the same. def combine[A, B, F[_]: Monad](fa: F[A], fb: F[B]) fixes that.

like image 89
Joe Pallas Avatar answered May 22 '23 05:05

Joe Pallas