[1]: Example: `[x*2 | x <- [1..10]]`
[1]: Example: `[x*2 | x <- [1..10]]`
do let x ← List.range' 1 10; return x^2
The syntax is flexible enough that you could build your own: macro "[" r:term "|" preamble:doElem "]" : term => `(do
$preamble; return $r)
#eval [x^2 | let x ← List.range' 1 10] declare_syntax_cat compClause
syntax "for " term " in " term : compClause
syntax "if " term : compClause
syntax "[" term " | " compClause,* "]" : term
macro_rules
| `([$t:term |]) => `([$t])
| `([$t:term | for $x in $xs]) => `(List.map (λ $x => $t) $xs)
| `([$t:term | if $x]) => `(if $x then [$t] else [])
| `([$t:term | $c, $cs,*]) => `(List.join [[$t | $cs,*] | $c])
#eval [x+1| for x in [1,2,3]]
-- [2, 3, 4]
#eval [4 | if 1 < 0]
-- []
#eval [4 | if 1 < 3]
-- [4]
#eval [(x, y) | for x in List.range 5, for y in List.range 5, if x + y <= 3]
-- [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (3, 0)]
(Your doElem idea is a good one though) (. * 2) <$> [1,2,3]
For example: def byTwo (inputList : List Nat) :=
(. * 2) <$> inputList
#eval byTwo [1, 2, 3]
-- [2, 4, 6]Why not? I was curious, Haskell is the functional language I know. Lean is the language I do not know.
Since Lean leans even heavier towards mathematics, set builder style notation seems like a natural fit. Now whether or not such notation is actually needed or worth it, that is a whole different question.
I think you'll usually see
def byTwo (inputList : List.Nat) := inputList.map (. \* 2)
rather than using `<$>`. There's also `inputList |>.map (. * 2)`, but I haven't seen it in any mathlib theory code yet, just Lean core or in metaprogramming. [x*y | x <- [1..10], y <- [2,3,5]] (*) <$> [1..10] <*> [2,3,5]
-- or
liftA2 (*) [1..10] [2,3,5]
Admittedly also not accessible to non-haskellers. But on the other hand, if you're going to learn a language, you ought to learn its idioms at some point.The nice thing nequo's example illustrates is rank polymorphism: list comprehensions work with lists, products of two, three, four,... lists with the same easy notation : `[n-ary function | x_1 <- List_1, ..., x_n <- List_n]`. It is quite nice to have this, especially for complex numerical operations.
Note also that unlike Lean 3, in Lean 4 `List` does not inherently implement `Applicative` or `Monad`, so your code cannot work as is.
It's not rocket science why someone would ask this. I don't always use list comprehensions. But sometimes I do. They have open arity and the syntax doesn't as often require things like parenthesis to handle fixity conflicts between other (non-applicative) operators. They are asking about list comprehensions, just because they think it's nice. It is a very simple question and talking about applicative is irrelevant.