Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String seen as a Monoid

Tags:

scala

scalaz

Given a signature like this one or that one:

def foo[A, F[_]](implicit mon: Monoid[F[A]], pr: Pure[F]): F[A]

Assuming A is Char, is there a way to get a String instead of a List[Char]?

String does not take a type parameter, so I assume it's not possible. What's the next best option? Right now, I use mkString on the result, but that doesn't feel optimal.

I think String is a monoid with zero "" and append +...

like image 405
huynhjl Avatar asked Oct 03 '11 06:10

huynhjl


2 Answers

It is possible to persuade String to masquerade as a higher-kinded type, and hence allow functions of the form of foo to be applicable. However, Scala's type inference isn't currently up to the job of inferring foo's type arguments, so you'll have to supply them explicitly,

// Assuming the the definitions of Pure and Monoid from Scalaz

type ConstString = {
  type λ[X] = String
}

implicit def StringPure = new Pure[ConstString#λ] {
  def pure[A](a: => A) = a.toString
}

val sm = implicitly[Monoid[String]]
val sp = implicitly[Pure[ConstString#λ]]
val f : String = foo[Char, ConstString#λ](sm, sp) // OK

Note that the Char type argument to foo is unused and can be anything, but must be something: in this case either Char is the natural choice, but Nothing or Any would do as well.

Note that this solution trades on String's special characteristics: values of all types are convertible to Strings so pure[A](a : => A) : String is implementable for all types A. Replicating this idiom for types other than String would most likely have to exploit some mechanism for implementing type-specific cases in the body of pure (eg. a pattern match of some sort).

like image 95
Miles Sabin Avatar answered Sep 18 '22 12:09

Miles Sabin


The best solution I can think of it is to define an implicit conversion from List[Char] to String.

like image 45
missingfaktor Avatar answered Sep 22 '22 12:09

missingfaktor