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
    • Zobrazit profil
    • E-mail
Re:Map vs. FlatMap
« Odpověď #61 kdy: 27. 09. 2016, 12:54:15 »
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:
Kód: [Vybrat]
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

  • *****
  • 1 983
    • Zobrazit profil
Re:Map vs. FlatMap
« Odpověď #62 kdy: 27. 09. 2016, 13:55:07 »
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:
Kód: [Vybrat]
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:
Kód: [Vybrat]
map fromJust $ filter isJust seznamJe 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
    • Zobrazit profil
    • E-mail
Re:Map vs. FlatMap
« Odpověď #63 kdy: 27. 09. 2016, 15:24:02 »
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:
Kód: [Vybrat]
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:
Kód: [Vybrat]
map fromJust $ filter isJust seznamJe 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 »
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 »
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 »
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

  • *****
  • 1 983
    • Zobrazit profil
Re:Map vs. FlatMap
« Odpověď #67 kdy: 27. 09. 2016, 19:44:40 »
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
Kód: [Vybrat]
[1, 2, 3] ve skutečnosti
Kód: [Vybrat]
1:2:3:[]

v

Re:Map vs. FlatMap
« Odpověď #68 kdy: 27. 09. 2016, 19:56:49 »
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
Kód: [Vybrat]
[1, 2, 3] ve skutečnosti
Kód: [Vybrat]
1:2:3:[]
nerozumím

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Map vs. FlatMap
« Odpověď #69 kdy: 27. 09. 2016, 20:36:27 »
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
Kód: [Vybrat]
[1, 2, 3] ve skutečnosti
Kód: [Vybrat]
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 »
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
Kód: [Vybrat]
[1, 2, 3] ve skutečnosti
Kód: [Vybrat]
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
    • Zobrazit profil
    • E-mail
Re:Map vs. FlatMap
« Odpověď #71 kdy: 27. 09. 2016, 21:35:19 »
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
Kód: [Vybrat]
[1, 2, 3] ve skutečnosti
Kód: [Vybrat]
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:
Kód: [Vybrat]
[[1],[2]].flatMap{$0}

v

Re:Map vs. FlatMap
« Odpověď #72 kdy: 27. 09. 2016, 21:38:24 »
Ve Swiftu:
Kód: [Vybrat]
[[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
    • Zobrazit profil
    • E-mail
Re:Map vs. FlatMap
« Odpověď #73 kdy: 27. 09. 2016, 21:53:30 »
Ve Swiftu:
Kód: [Vybrat]
[[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 »
Ve Swiftu:
Kód: [Vybrat]
[[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]