I am trying to come up with examples on how forA and map work similarly with just their arguments switched. The following code is an attempt at that:
encryptListUsingMap : [Text] -> [Text]
encryptListUsingMap x = map sha256 x
encryptListUsingForA: [Text] -> [Text]
encryptListUsingForA x = forA x sha256
The map sha256 x
works, but forA x sha256
doesn’t compile. The error message is
Couldn't match type ‘Text’ with ‘m b’
Expected type: Text -> m b
Actual type: Text -> Text
• In the second argument of ‘forA’, namely ‘sha256’
In the expression: forA x sha256
Does it have something to do with the way sha256 works?
Just to add to this, the following two statements work fine:
forA x (%) y
map (% y) x
Hi @Neelam_Dwivedi,
forA
is not “map
with its arguments switched”. If you want “map
with its arguments switched”, you can use (flip map)
.
Let’s take a look at their types:
map : (a -> b) -> [a] -> [b]
forA : (Applicative m) => [a] -> (a -> m b) -> m [b]
As you can see, there’s this Applicative
constraint in the way. You can think of forA
as the equivalent of map
but for actions.
Here’s a concrete example:
module Main where
import Daml.Script
pretend_script : Int -> Script Int
pretend_script x = return (x + 1)
setup : Script ()
setup = script do
let a : [Script Int] = map pretend_script [1, 2, 3]
let b : Script [Int] = forA [1, 2, 3] pretend_script
-- c <- a -- this line fails
d <- b -- this succeeds
e <- sequence a -- also succeeds
return ()
Notice the difference in types between a
and b
. Specifically, you can “unwrap” b
with <-
notation, but you can’t do the same for a
(without using the sequence
function).
For completeness:
sequence : (Applicative m) => [m a] -> m [a]
Thanks @Gary_Verhaegen
Yes, the documentation also compares forA with mapA, and not with map and so my guess was also that this has something to do with forA taking Applicative f, while map takes (a ->b). But I got thrown off when I saw that forA takes (%).
Thanks for a great explanation!