2011-10-03 18 views
5

Biorąc podpis jak ten lub that one:String postrzegane jako monoid

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

Zakładając jest Char, czy istnieje sposób, aby uzyskać String zamiast List[Char]?

String nie przyjmuje parametru typu, więc zakładam, że nie jest to możliwe. Jaka jest najlepsza opcja? Teraz używam mkString dla wyniku, ale to nie jest optymalne.

myślę String jest monoid z zerowej"" i dołączyć+ ...

+0

Dlaczego potrzebujesz Monoid [F [A]] zamiast tylko Monoid [F]? – CheatEx

+0

@CheatEx, w tym przypadku, nie jestem tym, który napisał 'foo', jestem tylko dzwoniącym. – huynhjl

Odpowiedz

7

Możliwe jest przekonanie napisu String do maskowania jako typu o wyższym typie, a tym samym umożliwienie stosowania funkcji formularza foo. Jednak Scala typu wnioskowanie nie jest obecnie do pracy wywodząc foo „s argumenty typu, więc będziesz musiał dostarczyć je wyraźnie,

// 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 

Należy pamiętać, że Char typu argument foo jest nieużywany i może być czymkolwiek, ale musi być czymś: w tym przypadku albo Char jest naturalnym wyborem, ale zrobiłby się równie dobrze Nothing lub Any.

Uwaga, że ​​to rozwiązanie Transakcje na szczególne cechy String dydaktycznego: Wartości wszystkich typów są wymienialne na String y tak pure[A](a : => A) : String jest wykonalne dla wszystkich typów A. Replikacja tego idiomu dla typów innych niż String najprawdopodobniej będzie musiała wykorzystywać pewien mechanizm do implementacji przypadków specyficznych dla danego typu w ciele pure (np. Dopasowanie do wzorca).

+2

Ale 'niejawnie [Pure [ConstString # λ]]. Pure ('a')' zwróci pusty łańcuch, więc nie jest to zbyt przydatne. Czy to jest? –

+0

Oczywiście potrzebna jest inna definicja 'Pure [ConstString # λ]' w celu wykonania jakiejkolwiek użytecznej pracy. Odpowiedź zredagowana, aby to odzwierciedlić. –

+0

Myślę, że widziałem Pustułkę! –

0

Twoja analiza, że ​​układ typu Scala odrzuci String jak nie bycie "wyższy typ kinded" * -> * jest poprawne. Oznacza to, że typ String nie jest przypisane do F[_] dla każdego F. Można spróbować (nie sprawdziłem tego) niejawne konwersje ...

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

... ale to nie będzie to przydatne I podejrzany, ponieważ w razie potrzeby musisz podać własne konwersje, ale także dlatego, że wydajność byłaby straszna, zakładając, że jest to gorąca część kodu.

Albo, używając standardowej biblioteki, można użyć maszyny CanBuildFrom ale to jest dalekie od oczywistości jak ładnie będzie mieszać się z typeclasses scalaz stylu.

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

W ciele metody, oczywiście, trzeba będzie użyć konstruktora do skonstruowania wartości zwracanej, w przeciwieństwie do monoid/pure typeclasses, czyniąc je nieco zbędny, podejrzewam.

6

Najlepszym rozwiązaniem, jakie mogę sobie wyobrazić, jest zdefiniowanie niejawnej konwersji z List[Char] na String.

Powiązane problemy