venta tipos sirven que para moda medidas lentes leer lectura hombre graduacion gafas anteojos haskell lens

haskell - sirven - tipos de lentes para leer



Usando una lente para leer mĂșltiples campos (2)

Al resolver la respuesta anterior de danidiaz , pude construir un Getter Prisoner (String, Int, Int) usando ReifiedGetter :

getNameRankAndCerealNumber_2 :: Prisoner -> (String, Int, Int) getNameRankAndCerealNumber_2 = p ^. nameRankAndCerealNumber_2 nameRankAndCerealNumber_2 :: Getter Prisoner (String, Int, Int) nameRankAndCerealNumber_2 = runGetter ((,,) <$> Getter name <*> Getter rank <*> Getter (cereal.number))

Y un Lens'' Prisoner (String, Int, Int) usando al alongside , aunque tuve que construir manualmente Iso'' ''s entre Prisoner y HList [String, Int, Int] y entre HList [a,b,c] y (a,b,c) .

getNameRankAndCerealNumber_3 :: Prisoner -> (String, Int, Int) getNameRankAndCerealNumber_3 p = p ^. nameRankAndCerealNumber_3 setNameRankAndCerealNumber_3 :: (String, Int, Int) -> Prisoner -> Prisoner setNameRankAndCerealNumber_3 t p = p & nameRankAndCerealNumber_3 .~ t nameRankAndCerealNumber_3 :: Lens'' Prisoner (String, Int, Int) nameRankAndCerealNumber_3 = hlist . alongside id (alongside id number) . triple where triple :: Iso'' (a,(b,c)) (a,b,c) triple = dimap (/(a,(b,c)) -> (a,b,c)) (fmap $ /(a,b,c) -> (a,(b,c))) hlist :: Iso'' Prisoner (String, (Int, Cereal)) hlist = dimap (/(P n r c) -> (n,(r,c))) (fmap $ /(n,(r,c)) -> P n r c)

Puede haber una forma más fácil de hacer esto, pero esa es otra pregunta.

Dados los tipos

data Prisoner = P { _name :: String , _rank :: Int , _cereal :: Cereal } data Cereal = C { _number :: Int , _percentDailyValue :: Map String Float , _mascot :: String }

Podría extraer el nombre, rango y número de cereal de alguien mediante la coincidencia de patrones:

getNameRankAndCerealNumber_0 :: Prisoner -> (String, Int, Int) getNameRankAndCerealNumber_0 (P { _name=name , _rank=rank , _cereal = C { _number=cerealNumber }} ) = (name, rank, cerealNumber)

Alternativamente, podría usar lentes para extraer cada parte por separado

makeLenses ''''Cereal makeLenses ''''Prisoner getNameRankAndCerealNumber_1 :: Prisoner -> (String, Int, Int) getNameRankAndCerealNumber_1 p = (p ^. name, p ^. rank, p ^. cereal.number)

¿Hay una manera de extraer los tres simultáneamente en un solo recorrido de la estructura de datos?

¿Alguna forma de combinar Getter s, Getter sa -> Getter sb -> Getter s (a,b) ?


Podemos usar la instancia ReifiedGetter del ReifiedGetter tipo de ReifiedGetter de Control.Lens.Reified :

runGetter $ (,) <$> Getter number <*> Getter mascot

En general, los nuevos tipos en Control.Lens.Reified ofrecen una gran cantidad de instancias muy útiles para getters y fold.

Nota n. ° 1 : observe que estamos combinando las lentes como captadores y obteniendo un captador a cambio. No se puede obtener una lente compuesta de esta manera, ya que habría problemas si sus "enfoques" se superponen. ¿Cuál podría ser el comportamiento apropiado del colocador en ese caso?

Nota n. ° 2 : la función alongside permite combinar dos lentes, obteniendo una lente auténtica que funciona en las dos mitades de un producto. Esto es diferente del caso anterior porque podemos estar seguros de que las lentes no se superponen. alongside es útil cuando su tipo es una tupla o tiene un isomorfismo en una tupla.