Map vs. FlatMap

Re:Map vs. FlatMap
« Odpověď #60 kdy: 26. 09. 2016, 08:16:39 »
@ava

S tím functorem máš pochopitelně pravdu, měl bych přestat psát na interweby před prvním kafem :-/


zboj

  • *****
  • 1 507
Re:Map vs. FlatMap
« Odpověď #61 kdy: 27. 09. 2016, 12:54:15 »
Citace od: BoneFlute kdy 26. 09. 2016, 01:19:26
Citace od: zboj kdy 25. 09. 2016, 16:02:26
Ještě by asi bylo vhodné dodat, že nemusí jít jen o kolekce, ale že jde o hodně obecný koncept fungující i s Optional, Future apod.
Na vstupu nebo na výstupu? Já mám teda flatMap zafixováno tak, že vrací vždy kolekci. V ostatních případech se používají funkce s jiným jménem.

Abych to ještě upřesnil a ukázal na příkladu, pokud mám např. seznam [1,2,nil,3] typu [Int?] a chci odfiltrovat nil (a dostat [Int]), použiju metodu "map" Optionalu:
list.flatMap{$0.map{[$0]} ?? []}
Nenulové prvky se "vytáhnou" z Optional a udělá se z nich singleton, zatímco nil se převede na prázdný seznam, z čehož pak flatMap zase udělá seznam (joinem).

BoneFlute

  • *****
  • 2 155
Re:Map vs. FlatMap
« Odpověď #62 kdy: 27. 09. 2016, 13:55:07 »
Citace od: zboj kdy 27. 09. 2016, 12:54:15
Citace od: BoneFlute kdy 26. 09. 2016, 01:19:26
Citace od: zboj kdy 25. 09. 2016, 16:02:26
Ještě by asi bylo vhodné dodat, že nemusí jít jen o kolekce, ale že jde o hodně obecný koncept fungující i s Optional, Future apod.
Na vstupu nebo na výstupu? Já mám teda flatMap zafixováno tak, že vrací vždy kolekci. V ostatních případech se používají funkce s jiným jménem.

Abych to ještě upřesnil a ukázal na příkladu, pokud mám např. seznam [1,2,nil,3] typu [Int?] a chci odfiltrovat nil (a dostat [Int]), použiju metodu "map" Optionalu:
list.flatMap{$0.map{[$0]} ?? []}
Nenulové prvky se "vytáhnou" z Optional a udělá se z nich singleton, zatímco nil se převede na prázdný seznam, z čehož pak flatMap zase udělá seznam (joinem).
Neříkám, že ten tvůj způsob postrádá eleganci... Ale přijde mi, že jen využíváš chování flatMap, než, že by to na toto bylo určeno.

Já bych to třeba napsal takto:
map fromJust $ filter isJust seznam
Je to humpolácké, a mechanické, uznávám :-)

Každopádně, mám naučené spíše takové využití, kdy mám pole funkcí vracející pole. A nechci pole polí, ale, protože mi nezáleží na indexu, ale jen existenci, tak jen jednoúrovňové pole. Nebo když mám strom, a chci v něm najít výskyt nějakých prvků.

Takže mě oprav, na vstupu může být cokoliv, na výstupu je kolekce/pole. Nebo může být na výstupu i Future?

zboj

  • *****
  • 1 507
Re:Map vs. FlatMap
« Odpověď #63 kdy: 27. 09. 2016, 15:24:02 »
Citace od: BoneFlute kdy 27. 09. 2016, 13:55:07
Citace od: zboj kdy 27. 09. 2016, 12:54:15
Citace od: BoneFlute kdy 26. 09. 2016, 01:19:26
Citace od: zboj kdy 25. 09. 2016, 16:02:26
Ještě by asi bylo vhodné dodat, že nemusí jít jen o kolekce, ale že jde o hodně obecný koncept fungující i s Optional, Future apod.
Na vstupu nebo na výstupu? Já mám teda flatMap zafixováno tak, že vrací vždy kolekci. V ostatních případech se používají funkce s jiným jménem.

Abych to ještě upřesnil a ukázal na příkladu, pokud mám např. seznam [1,2,nil,3] typu [Int?] a chci odfiltrovat nil (a dostat [Int]), použiju metodu "map" Optionalu:
list.flatMap{$0.map{[$0]} ?? []}
Nenulové prvky se "vytáhnou" z Optional a udělá se z nich singleton, zatímco nil se převede na prázdný seznam, z čehož pak flatMap zase udělá seznam (joinem).
Neříkám, že ten tvůj způsob postrádá eleganci... Ale přijde mi, že jen využíváš chování flatMap, než, že by to na toto bylo určeno.

Já bych to třeba napsal takto:
map fromJust $ filter isJust seznam
Je to humpolácké, a mechanické, uznávám :-)

Každopádně, mám naučené spíše takové využití, kdy mám pole funkcí vracející pole. A nechci pole polí, ale, protože mi nezáleží na indexu, ale jen existenci, tak jen jednoúrovňové pole. Nebo když mám strom, a chci v něm najít výskyt nějakých prvků.

Takže mě oprav, na vstupu může být cokoliv, na výstupu je kolekce/pole. Nebo může být na výstupu i Future?
Jistě, na výstupu může cokoliv komplexního (přesněji jakýkoliv komplexní typ splňující monadické zákony), takže třeba Future nebo Optional, u Optional pak typ funkce bude T->T?. Nebo když to bude Future, dá se pak volání více funkcí pomocí flatMap zřetězit. Akorát by pak asi bylo lepší pojmenovat funkci "joinMap", ale to je jen terminologie, ostatně v Haskellu se tomu říká "bind" (což dává smysl pro různé typy kolekcí, kontejnerů apod.) a konvencí pro tuto operaci je >>=.

v

Re:Map vs. FlatMap
« Odpověď #64 kdy: 27. 09. 2016, 16:43:24 »
Citace od: zboj kdy 27. 09. 2016, 15:24:02
Jistě, na výstupu může cokoliv komplexního (přesněji jakýkoliv komplexní typ splňující monadické zákony), takže třeba Future nebo Optional, u Optional pak typ funkce bude T->T?. Nebo když to bude Future, dá se pak volání více funkcí pomocí flatMap zřetězit. Akorát by pak asi bylo lepší pojmenovat funkci "joinMap", ale to je jen terminologie, ostatně v Haskellu se tomu říká "bind" (což dává smysl pro různé typy kolekcí, kontejnerů apod.) a konvencí pro tuto operaci je >>=.
to se mi nějak nezdá, jak se pomocí monadického rozhraní poskládá (např.) seznam?


Re:Map vs. FlatMap
« Odpověď #65 kdy: 27. 09. 2016, 16:57:33 »
Citace od: v kdy 27. 09. 2016, 16:43:24
to se mi nějak nezdá, jak se pomocí monadického rozhraní poskládá (např.) seznam?

Pokud jsem pochopil otazku, tak by mohlo vysvetlit tohle:
https://en.wikibooks.org/wiki/Haskell/Understanding_monads/List

v

Re:Map vs. FlatMap
« Odpověď #66 kdy: 27. 09. 2016, 17:09:23 »
Citace od: Ondra Satai Nekola kdy 27. 09. 2016, 16:57:33
Citace od: v kdy 27. 09. 2016, 16:43:24
to se mi nějak nezdá, jak se pomocí monadického rozhraní poskládá (např.) seznam?

Pokud jsem pochopil otazku, tak by mohlo vysvetlit tohle:
https://en.wikibooks.org/wiki/Haskell/Understanding_monads/List
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]

BoneFlute

  • *****
  • 2 155
Re:Map vs. FlatMap
« Odpověď #67 kdy: 27. 09. 2016, 19:44:40 »
Citace od: v kdy 27. 09. 2016, 17:09:23
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]
Možná jestli to nebude podobné, jako ten detail, že v Haskellu je [1, 2, 3] ve skutečnosti 1:2:3:[]

v

Re:Map vs. FlatMap
« Odpověď #68 kdy: 27. 09. 2016, 19:56:49 »
Citace od: BoneFlute kdy 27. 09. 2016, 19:44:40
Citace od: v kdy 27. 09. 2016, 17:09:23
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]
Možná jestli to nebude podobné, jako ten detail, že v Haskellu je [1, 2, 3] ve skutečnosti 1:2:3:[]
nerozumím

zboj

  • *****
  • 1 507
Re:Map vs. FlatMap
« Odpověď #69 kdy: 27. 09. 2016, 20:36:27 »
Citace od: BoneFlute kdy 27. 09. 2016, 19:44:40
Citace od: v kdy 27. 09. 2016, 17:09:23
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]
Možná jestli to nebude podobné, jako ten detail, že v Haskellu je [1, 2, 3] ve skutečnosti 1:2:3:[]
Na konkrétní implementaci nijak nezáleží. Streamy (např. v Javě) fungují podobně. V případě [1] a [2] stačí udělat jen "join" (aka "flatten") (což není přímá odpověď na otázku, jak to udělat pomocí >>=, ale "join" je jen x>>=id, kde id je identické zobrazení).

v

Re:Map vs. FlatMap
« Odpověď #70 kdy: 27. 09. 2016, 20:49:33 »
Citace od: zboj kdy 27. 09. 2016, 20:36:27
Citace od: BoneFlute kdy 27. 09. 2016, 19:44:40
Citace od: v kdy 27. 09. 2016, 17:09:23
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]
Možná jestli to nebude podobné, jako ten detail, že v Haskellu je [1, 2, 3] ve skutečnosti 1:2:3:[]
Na konkrétní implementaci nijak nezáleží. Streamy (např. v Javě) fungují podobně. V případě [1] a [2] stačí udělat jen "join" (aka "flatten") (což není přímá odpověď na otázku, jak to udělat pomocí >>=, ale "join" je jen x>>=id, kde id je identické zobrazení).
no a jak se to teda udělá?

zboj

  • *****
  • 1 507
Re:Map vs. FlatMap
« Odpověď #71 kdy: 27. 09. 2016, 21:35:19 »
Citace od: v kdy 27. 09. 2016, 20:49:33
Citace od: zboj kdy 27. 09. 2016, 20:36:27
Citace od: BoneFlute kdy 27. 09. 2016, 19:44:40
Citace od: v kdy 27. 09. 2016, 17:09:23
možná tam je, ale já ji nevidim, možná jsem se v tom trošku ztratil
otázka by mohla být jak pomocí (>>=) a return (když už teda chcete haskell) udělám z [1] a [2] hodnotu [1,2]
Možná jestli to nebude podobné, jako ten detail, že v Haskellu je [1, 2, 3] ve skutečnosti 1:2:3:[]
Na konkrétní implementaci nijak nezáleží. Streamy (např. v Javě) fungují podobně. V případě [1] a [2] stačí udělat jen "join" (aka "flatten") (což není přímá odpověď na otázku, jak to udělat pomocí >>=, ale "join" je jen x>>=id, kde id je identické zobrazení).
no a jak se to teda udělá?
Ve Swiftu:
[[1],[2]].flatMap{$0}

v

Re:Map vs. FlatMap
« Odpověď #72 kdy: 27. 09. 2016, 21:38:24 »
Citace od: zboj kdy 27. 09. 2016, 21:35:19
Ve Swiftu:
[[1],[2]].flatMap{$0}
swift neznám, ale řekl bych, že ekvivalentní kód v haskellu by byl join [[1], [2]] - jenže to není odpověď na mou otázku

zboj

  • *****
  • 1 507
Re:Map vs. FlatMap
« Odpověď #73 kdy: 27. 09. 2016, 21:53:30 »
Citace od: v kdy 27. 09. 2016, 21:38:24
Citace od: zboj kdy 27. 09. 2016, 21:35:19
Ve Swiftu:
[[1],[2]].flatMap{$0}
swift neznám, ale řekl bych, že ekvivalentní kód v haskellu by byl join [[1], [2]] - jenže to není odpověď na mou otázku
V tom případě doporučuju tu otázku přeformulovat, evidentně jsem ji špatně pochopil. BTW ekvivalentní není, to by bylo [[1],[2]].flatten()

v

Re:Map vs. FlatMap
« Odpověď #74 kdy: 27. 09. 2016, 22:03:51 »
Citace od: zboj kdy 27. 09. 2016, 21:53:30
Citace od: v kdy 27. 09. 2016, 21:38:24
Citace od: zboj kdy 27. 09. 2016, 21:35:19
Ve Swiftu:
[[1],[2]].flatMap{$0}
swift neznám, ale řekl bych, že ekvivalentní kód v haskellu by byl join [[1], [2]] - jenže to není odpověď na mou otázku
V tom případě doporučuju tu otázku přeformulovat, evidentně jsem ji špatně pochopil. BTW ekvivalentní není, to by bylo [[1],[2]].flatten()
pomocí syntaxe haskellu:
implementace funkce f
f :: Monad m => m a  -> m a -> m a
tak aby f [1] [2] == [1,2]