by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Garrett Kelsch
@gameslayer103
Here is a link to the page: http://eed3si9n.com/herding-cats/PartialOrder.html
Andi Miller
@andimiller
along with Eq it's more type safe than the normal implementations
Gavin Bisesi
@Daenyth
@gameslayer103 It allows their use on values which are provided just as type parameters
and also what Andi says
Garrett Kelsch
@gameslayer103
Ok, that makes a lot of sense. Thanks!
Billzabob
@Billzabob
1.pure[Future] is the equivalent of Future.successful(1), what is the equivalent of Future.failed(new Exception("foo")? Guessing something with MonadError?
Gavin Bisesi
@Daenyth
(new Exception("foo")).raiseError[Future]
ApplicativeError
raiseError[F[_]](e: E) given ApplicativeError[F, E]
Billzabob
@Billzabob
@Daenyth Thanks!
Stephen Duncan Jr
@jrduncans
It’s def raiseError[F[_], A](implicit F: ApplicativeError[F, _ >: E]): F[A] so, you need (new Exception(“foo”)).raiseError[Future, Int], right?
Rob Norris
@tpolecat
Yes
Christopher Davenport
@ChristopherDavenport
Ooh, existential. Intriguing. I always write it F[_]: ApplicativeError[?[_], Throwable]
Rob Norris
@tpolecat
That kind of inference doesn't work very well. If you want foo.raiseError to widen foo you need to use a <:< to do it, as far as I can tell. I was messing with it yesterday.
Fabio Labella
@SystemFw
yeah most of the time it won't work, you have to. do (new Exception : Throwable).raiseError[F, Int]) at which point F.raiseError(new Exception) is more appealing
Gavin Bisesi
@Daenyth
I usually do the F.raise.. out of habit, didn't realize the inference was nicer
Stephen Duncan Jr
@jrduncans

Hmm. I didn’t see any cases of that problem in my usage.

On a related note: if you’re wirting tests and you need an ApplicativeError or MonadError, do you just jump to using IO (or, in my situation, StateT[IO, MyState, ?] because I need MonadState and MonadError)? Or something less powerful than IO? Try?

Gavin Bisesi
@Daenyth
Depends what I'm doing
Either is a pretty easy one
I usually factor typeclass dependencies to be precise for code isolation and semantic information to the reader, rather than so I can actually use non-IO in tests
Billzabob
@Billzabob
Why does Free in cats have Pure, Suspend, and FlatMapped but in Haskell it just has Pure a and Free (f ( Free f a))?
Gavin Bisesi
@Daenyth
Probably because haskell is always lazy
Fabio Labella
@SystemFw
stack safety
cats Free is also a bit different in that it factors in Coyoneda as well, so it's actually closer to Coyoneda in haskell
Billzabob
@Billzabob
Haven't heard of Coyoneda. That's quite the name. How do you pronounce it?
Fabio Labella
@SystemFw

a good way of looking at it is noting how Monad can be expressed as either (forgetting Applicative)

class Functor f => Monad f where
  pure :: a -> f a
  join :: f (f a) -> f a

or

class Monad f where
   pure :: a -> f a
   (>>=) ::  f a -> (a -> f b) -> f b

.
The first definition gives rise to

data Free f a = Pure a | Roll (f (Free f a))
instance Functor f => Monad (Free f) where ...

and your algebra looks this way:

data Alg a = Put String a | Get String (String -> a)
 instance Functor Alg where

The second definition, which is Operational (and cats Free) gives rise to

data Free f a where
  Pure  ::  a ->  Free fa
  FlatMap ::  f a  -> (a -> Free f b) -> Free f b

instance Monad (Free f a) -- note no Functor

and your algebra looks this way

data Alg a where
   Put :: String -> Alg ()
   Get :: String -> Alg String

and no Functor needed

at first people thought these two were two different things
Fabio Labella
@SystemFw
but it turns out the second (Operational) can be understood as being the first, except f is Coyoneda f , and Coyoneda is basically the Free Functor
which is why you don't need to explicitly declare a Functor for your algebra
class Functor f where
   fmap :: (a -> b) -> f a -> f b

data Coyoneda f a where
   Fmap :: (a -> b) -> f b -> Coyoneda f a
in Scala, for a while we were literally doing Free[Coyoneda[F, ?], A] (with a FreeC type synonym)
until it got folded in, and then it ended up looking like Operational
Rob Norris
@tpolecat
Free of Coyoneda was the :fire: for a long time. It really opened things up.
Billzabob
@Billzabob
That's a lot to take in but I love when I get something new to learn about from here. One more question: Is there an implementation of a rose tree with the appropriate cats type-class instances somewhere or should I just try and roll my own?
Fabio Labella
@SystemFw
@Billzabob funnily enough, that's Cofree
using List as the pattern functor
Billzabob
@Billzabob
@SystemFw Interesting how often things seem to tie together like that.
Fabio Labella
@SystemFw
yet another way to look at Free (especially evident in the first version) is as a tree with a Functorful f of children, and values at the leaves (the Pure constructor is Leaf a, and Roll is the branch, with f children). If you look at Cofree, that's also a Tree with values at the branches instead, and again whose structure is determined by f, and that's a Rose Tree
data Free f a = Leaf a | Node f (Free f a)
data Cofree f a = Node a (f (Cofree f a))
type Rose = Cofree []
-- replace and you get
data Rose a = Node a [Rose a]
Igor Postanogov
@ipostanogov

Hi!

If I have Map[String, Int] & f: Int => ValidatedNec[String, Bool], I can get Map[String, ValidatedNec[String, Bool]] via mapValues.
Is there any way to get ValidatedNec[String, Map[String, Bool]] from it?

Oleg Pyzhcov
@oleg-py
import alleycats.std.map._ and then traverse?
Igor Postanogov
@ipostanogov
@oleg-py, it works, thanks!
Soren
@srnb_gitlab
How do I dropWhile a List[F[T]] based on F[T] => F[Boolean]?
A solution using sequencing is not what I want because I don't want to evaluate the F[T]s later in the list
Gavin Bisesi
@Daenyth
@srnb_gitlab I recommend fs2
Oleg Pyzhcov
@oleg-py
or manual recursion
Gavin Bisesi
@Daenyth
val lst: List[F[T]] = ???
fs2.Stream.emits(lst)  // Stream[Pure, F[T]]
  .evalMap(identity)   // Stream[F, T]
  .evalMap(t => cond(t).map(b => (t, b))) // Stream[F, (T, B)]
  .dropWhile(tb => tb._2)
  .map(_._1) // Stream[F, T]
Oleg Pyzhcov
@oleg-py
def dropWhileM[F[_]: Monad, A](list: List[F[A]])(fn: F[A] => F[Boolean]): F[List[F[A]]] = list match {
  case fa :: fas => fn(fa).ifM( dropWhileM(fas)(fn), list.pure[F] )
  case _ => list.pure[F]
}
wonder why you'd want F[A] => F[Boolean] instead of A => F[Boolean] tho