Haskell: applying a function to all combinations of arguments

I post below code in Haskell. Please consider the code as an example, which I am going to use to explain what I would like to know.

try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try (a:as) (b:bs) (c:cs)  | ((checkIfCorrect a b c) == True) =  a:b:[c]
                          | otherwise = try as bs cs 

checkIfCorrect :: [Char] -> [Char] -> [Char] -> Bool
checkIfCorrect a b c = True

In the end, checkIfCorrectreturns Truefor only one combination of arguments. checkIfCorrectis a really long feature, so I decided to post a replacement here. In the above example, the function checkIfCorrectis applied (by function try) to: first [Char]in the first list, first [Char]in the second list and first in the [Char]third. If the first protected equation is not executed, the function checkIfCorrectis applied to: second [Char]in the first list ... and so on. What I would like to achieve is to apply a function checkIfCorrect(by function try) to all combinations [Char]from all lists ( [[Char]]). I mean the following (for example): third [Char]in the first list, eighth [Char]in the second list, eleventh[Char]in the third list and so on. All with everyone. How could I easily achieve this?

+6
source share
3 answers

I just wanted to show you an alternative way to write @WillemVanOnsem code . I assume that you are new to Haskell, so I hope this answer gives you a tiny look at a rich and great idea that you will soon be fully aware of as you progress through the language. Therefore, do not worry too much if you do not immediately understand everything about this code; I'm just trying to give you a taste!

The list explanation can always be reformulated using the list monad:

import Control.Monad (guard)

try as bs cs = head $ do
    a <- as
    b <- bs
    c <- cs
    guard $ checkIfCorrect a b c
    return [a,b,c]

do : a as, b bs c cs, [a,b,c], checkIfCorrect True. : "" "", <-, "" guard, "yield" s return s.

, Python, :

def try(as, bs, cs):
    for a in as:
        for b in bs:
            for c in cs:
                if checkIfCorrect(a, b, c):
                    yield [a,b,c]

, . "" , , ( " " JS), , . , , do -notation.

+11

, :

try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try as bs cs = head [ [a,b,c] | a <- as, b <- bs, c <- cs, checkIfCorrect a b c ]
--                    \__ __/   \__________ ____________/  \__________ _______/
--                       v                 v                          v
--                     yield           enumeration                 filter

: < "( ). a <- as, b <- bs, c <- cs, , a as, a, b bs .. , .

": checkIfCorrect a b c, , True, " ".

" yield". , ( ), . , [a,b,c]. , , . , , : , , , , ..

head ( ). head :: [a] -> a . , try , .

+5

Willem Van Onsem Orgazoid (upvoted), , .

:

import Control.Monad (MonadPlus, mfilter)
import Data.Maybe (fromMaybe, listToMaybe)

, as, bs cs. Applicative:

combinations = (,,) <$> as <*> bs <*> cs

(,,) - , ( ) .

, :

*Prelude> (,,) <$> [1,2] <*> ["foo", "bar"] <*> [True, False]
[(1,"foo",True),(1,"foo",False),(1,"bar",True),(1,"bar",False),(2,"foo",True),(2,"foo",False),(2,"bar",True),(2,"bar",False)]

, , Maybe s:

*Prelude> (,,) <$> Just 1 <*> Just "foo" <*> Just False
Just (1,"foo",False)

​​ :

try' :: MonadPlus m => ((a, a, a) -> Bool) -> m a -> m a -> m a -> m [a]
try' predicate as bs cs =
  tripleToList <$> mfilter predicate combinations
  where
    combinations = (,,) <$> as <*> bs <*> cs
    tripleToList (a, b, c) = [a, b, c]

, . MonadPlus a.

:

*Answer> try' (const True) ["foo", "bar", "baz"] ["qux", "quux", "quuz", "corge"] ["grault", "garply"]
[["foo","qux","grault"],["foo","qux","garply"],["foo","quux","grault"],["foo","quux","garply"],["foo","quuz","grault"],["foo","quuz","garply"],["foo","corge","grault"],["foo","corge","garply"],["bar","qux","grault"],["bar","qux","garply"],["bar","quux","grault"],["bar","quux","garply"],["bar","quuz","grault"],["bar","quuz","garply"],["bar","corge","grault"],["bar","corge","garply"],["baz","qux","grault"],["baz","qux","garply"],["baz","quux","grault"],["baz","quux","garply"],["baz","quuz","grault"],["baz","quuz","garply"],["baz","corge","grault"],["baz","corge","garply"]]
*Answer> try' (const False) ["foo", "bar", "baz"] ["qux", "quux", "quuz", "corge"] ["grault", "garply"]
[]
*Answer> try' (const True) (Just "foo") (Just "bar") (Just "baz")
Just ["foo","bar","baz"]
*Answer> try' (const False) (Just "foo") (Just "bar") (Just "baz")
Nothing

, predicate False, . ; Maybe Nothing.

, checkIfCorrect . , , . , try' checkIfCorrect:

try :: [String] -> [String] -> [String] -> [String]
try as bs cs = fromMaybe [] $ listToMaybe $ try' isCorrect as bs cs
  where isCorrect (a, b, c) = checkIfCorrect a b c

Here I created a private function isCorrectto offload the function checkIfCorrect. Then I used a combination of listToMaybeand fromMaybeto return the first element of the resulting list. Other answers are used here head, but this will throw an exception if the list is empty, so I used this combination because it is safe.

+3
source

All Articles