2011-10-04 18 views
11

Quiero llamar al método pure de Scalaz para poner un valor en la mónada de estado. Las siguientes obras:En Scala, ¿hay una forma abreviada de reducir la aridad de un tipo genérico?

type IntState[A] = State[Int, A] 
val a = "a".pure[IntState] 
a(1) 
    (Int, java.lang.String) = (1,a) 

También puede eliminar el tipo de alias (gracias de Scalaz Pure.scala):

val a = "a".pure[({type T[A]=State[Int,A]})#T] 
a(1) 
    (Int, java.lang.String) = (1,a) 

Pero eso es muy torpe. ¿Hay una manera más corta de sintetizar un tipo como este? Al igual que la sintaxis marcador de posición para los literales de la función, ¿hay algo como:

"a".pure[State[Int, *]] 
+0

No creo que Scala tenga dicho azúcar sintáctico, ya que [la aplicación de tipo parcial citada por michid] (http://stackoverflow.com/questions/7045967/what-are-type-projections-useful-for/7046860#7046860) como un ejemplo de la utilidad de las proyecciones de tipo. –

Respuesta

6

Para la aplicación concisa parcial tipo (aridad-2) en Scala, puede infija tipo notación los siguientes.

type ![F[_, _], X] = TF { type ![Y] = F[X, Y] } 

"a".pure[(State!Int)# !] 

Tenga en cuenta que podemos notación infija para dos constructor de tipos aridad (o tipo de alias).

+0

Cambiaría el nombre del segundo '!' A '?', Así podría escribir '(State! Int) #?'. –

+5

El nombre de no operador sería preferible para el miembro de tipo, por lo que puede omitir el espacio después de la proyección de tipo, es decir: 'rasgo! [F [_, _], A] {tipo X [B] = F [A, B ]}; foo [(State! Int) #X] '. No creas que puede ser mucho más compacto que eso. –

6

No estoy seguro si esto califica como mejor, pero aquí es un enfoque que @kmizu twitteó el otro día:

scala> trait TF { 
    | type Apply[A] 
    | } 
defined trait TF 

scala> type Curried2[F[_, _]] = TF { 
    | type Apply[X] = TF { 
    |  type Apply[Y] = F[X, Y] 
    | } 
    | } 
defined type alias Curried2 

scala> "a".pure[Curried2[State]#Apply[Int]#Apply] 
res7: scalaz.State[Int,java.lang.String] = [email protected] 

Usted puede hacer se ve un poco mejor mediante el uso de alias de tipo simbólico.

scala> type ![F[_, _]] = TF { 
    | type ![X] = TF { 
    |  type ![Y] = F[X, Y] 
    | } 
    | } 
defined type alias $bang 

scala> "a".pure[![State]# ![Int]# !] 
res9: scalaz.State[Int,java.lang.String] = [email protected] 
+0

¿Qué sucede cuando quiere vincular el primer parámetro de tipo? ¿Supongo que necesitas otra versión de Curried2? – IttayD

+1

@IttayD: Eso no se llama currying, y sería mejor utilizar la sintaxis de tipo lambda en ese caso. (Esta pequeña ventaja de la sintaxis de tipo lambda sobre la sintaxis del constructor de tipo currículo de Haskell también fue notada por Tony Morris en alguna lista de correo). La sintaxis que he sugerido en esta respuesta es para emular la aplicación de tipo parcial de estilo Haskell. '! [State] #!' Es equivalente a 'State' en Haskell,'! [State] #! [Int] #! 'To' State Int' etc. – missingfaktor

+0

@Downvoter: ¿Le importa explicar su voto? – missingfaktor

1

la forma más popular de reducir arity es el complemento kind-projector (https://github.com/non/kind-projector) que también se utiliza en la biblioteca de gatos. Al permitir que este plugin que su ejemplo se puede transformar en:

val a = "a".pure[State[Int, ?]] 

Nota: esta sintaxis será habilitado en manchado por defecto.

Cuestiones relacionadas