Perché il sollevamento della funzione binaria nella lista monadi supera tutte le combinazioni di elementi?

2

Dire, se voglio creare un prodotto cartesiano di due liste, potrei fare (qui in Haskell, ma posso fare lo stesso ad esempio in Scala o qualsiasi altra lingua in grado di FP)

cartesianProd = liftM2 (,)

quindi

>cartesianProd [1,2] [3,4]
>[(1,3),(1,4),(2,3),(2,4)] 

Ovviamente, usando (sollevamento) + invece di paia di tuple, produrrà una lista di somme di tutte le combinazioni.

Per definizione FP, " lifting è un concetto che ti consente di trasformare una funzione in una funzione corrispondente all'interno di un'altra ( di solito più generale). " Il modo in cui lo capisco, se ho argomenti monadici, posso trasformare la mia funzione binaria in modo che funzioni con loro tramite liftM2. Ma da dove viene il prodotto cartesiano? Intuitivamente, mi aspetto [(1,3), (2,4)] dall'esempio sopra.

    
posta Alex Pakka 14.02.2014 - 02:35
fonte

2 risposte

0

Non so molto di Haskell ma per la tua domanda ti consiglio di leggere questa sezione di Learn You a Haskell: link .

L'essenza di ciò è che alcuni tipi potrebbero soddisfare classi come le leggi del functor o della monade in più di un modo. Le liste per esempio potrebbero essere dei funtori applicativi nel modo in cui sono nella libreria standard di haskell (applica la funzione a ogni possibilità da ciascuna lista), oppure potrebbero essere dei funtori applicativi nel modo in cui ci si aspetta che siano (applicare la funzione ai corrispondenti elementi nelle liste).

I progettisti di haskell pensavano che la versione del prodotto cartesiana fosse più utile, così hanno reso l'interpretazione predefinita. Hanno anche capito che la tua interpretazione soddisfaceva anche le leggi appropriate ed era anche utile e quindi dovresti provare a eseguire il codice seguente.

module Main where

import qualified Control.Applicative as CA

prod :: (CA.Applicative f) => f a -> f b -> f (a, b)
prod = CA.liftA2 (,)

main :: IO ()
main = do 
        print $ prod [1,2] [3,4]
        print . CA.getZipList $ prod (CA.ZipList [1,2]) (CA.ZipList [3,4])
    
risposta data 14.02.2014 - 03:56
fonte
1

La ragione è che il M in liftM2 significa monade. Infatti liftM2 è definito come

 liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
 liftM2 f a b = do
   a' <- a
   b' <- b
   return (f a b)

Questo dipende dall'operazione di bind monadico >>= :: m a -> (a -> m b) -> m b . In un elenco, >>= equivale a concatMap , quindi il tuo codice è

 cartProd f a b = concatMap (\a' -> concatMap (\b' -> f a b) b) a

Questo applica (,) a ogni coppia di a se b s nel nostro elenco e così otteniamo un prodotto cartesiano. Per inciso, sarebbe meglio usare liftA2 che funzioni su tutte le monadi + applicative.

Salterò sulla questione spinosa del perché la lista monad sia concatMap e la releghiamo finché non la trovi in un bel libro come LYAH o Real World Haskell. Invece il comportamento che vuoi è zip o il più generale zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] .

    
risposta data 14.02.2014 - 06:47
fonte

Leggi altre domande sui tag