una simbolos salir numeros mónada multiplicar monadas lista leer functores aleatorios haskell conduit

haskell - simbolos - ¿Cuál es la forma preferida de combinar dos sumideros?



salir de haskell (2)

He usado zipSinks :: Monad m => Sink imr -> Sink imr'' -> Sink im (r, r'') para esto, pero se considera obsoleto.


((El paquete es conduit-0.5.2.3 . Todo el module es solo para compatibilidad con versiones anteriores.))

[ editar ]

Por lo tanto, mi suposición simple y monádica ( ver más abajo ) parece estar equivocada , aunque los tipos sean correctos. Ahora, solo puedo adivinar que la respuesta es:

Las funciones de reemplazo aún están en desarrollo, al igual que todas las tuberías y conductos y conceptos y bibliotecas similares.

Espero a que la próxima API resuelva esta pregunta y siga usando zipSink hasta entonces. (Tal vez fue simplemente fuera de lugar.)

[ / editar ]

No estoy tan familiarizado con este paquete, ¿pero no haría lo mismo que esto?

zipSinks :: Monad m => Sink i m r -> Sink i m r'' -> Sink i m (r, r'') zipSinks s1 s2 = (,) <$> s1 <*> s2

Es una Monad después de todo. ( Functor , Applicative )

zipSinks :: Monad sink => sink r -> sink r'' -> sink (r, r'') zipSinks s1 s2 = liftM2 (,) s1 s2


Editar

Después de considerar esto, no creo que sea posible con la versión actual de Data.Conduit. Las tuberías no son categorías, por lo que &&& está fuera de cuestión. Y no se me ocurre ninguna forma de obtener resultados del flujo ascendente, enviarlos de forma incremental a ambos sumideros y cortocircuitarlos cuando finaliza el primer sumidero. (Aunque no creo que Data.Conduit.Util.zipSinks cortocircuite de esta manera, parece que sería muy deseable.) Excepto, por supuesto, para la coincidencia de patrones en ambos Sinks (como lo hace zipSinks en el paquete), Pero eso es lo que estamos tratando de evitar aquí.

Dicho esto, me encantaría estar equivocado aquí.

No es bonito, pero puedes hacer esto de una manera bastante obvia.

Primeras importaciones:

module Main where import Control.Monad.Trans import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import qualified Data.Conduit.Text as CT import qualified Data.Conduit.Util as CU import Data.Maybe import Data.Text (unpack)

Ahora para zipSinks . Básicamente, usted desea crear un receptor que extraiga la entrada del flujo ascendente y lo envíe a cada receptor secundario por separado. En este caso, he usado CL.sourceList para hacer esto. Si maybeToList devuelve Nothing , maybeToList devuelve una lista vacía, por lo que los sumideros secundarios también se ejecutan sin entrada. Finalmente, la salida de cada fregadero infantil se alimenta a la tupla.

zipSinks :: Monad m => Sink i m r -> Sink i m r'' -> Sink i m (r, r'') zipSinks s1 s2 = do l <- fmap maybeToList await o1 <- lift $ CL.sourceList l $$ s1 o2 <- lift $ CL.sourceList l $$ s2 return (o1, o2)

Aquí hay algunos ejemplos de zipSinks usar zipSinks . Parece que funciona bien tanto dentro de IO como fuera de él, y en las pocas pruebas que hice, la salida coincide con la salida de zipped'' , creada con los antiguos zipSinks .

doubleHead :: Monad m => Sink Int m (Maybe Int) doubleHead = await >>= return . fmap (2*) -- old version zipped'' :: Monad m => Sink Int m (Maybe Int, Maybe Int) zipped'' = CU.zipSinks CL.head doubleHead -- new version zipped :: Monad m => Sink Int m (Maybe Int, Maybe Int) zipped = zipSinks CL.head doubleHead fromList = CL.sourceList [7, 8, 9] $$ zipped -- (Just 7, Just 14) fromFile :: String -> IO (Maybe Int, Maybe Int) fromFile filename = runResourceT $ CB.sourceFile filename $= CB.lines $= CT.decode CT.utf8 $= CL.map (read . unpack) $$ zipped -- for a file with the lines: -- -- 1 -- 2 -- 3 -- -- returns (Just 1, Just 2)