3 ms·
('a':_) <- x = x : f zs What's the `<- x`for? I know some Haskell and I've never seen that syntax. And `('a':_) = x : f zs` should be enough I think. Also I'
by uryga 10y ago
('a':_) <- x = x : f zs
What's the `<- x`for? I know some Haskell and I've never seen that syntax. And `('a':_) = x : f zs` should be enough I think.
Also I'm pretty sure each line is supposed to be a string, so it should be `("a":_) = x : f zs` :)
- dllthomas 10y agoThat's pattern-guard syntax. The bits between | and = ("the guard") are tried in turn, and the stuff to the right of the = is done for the first that succeeds. This can also introduce new bindings, although it doesn't here. To do this directly without guards, it'd be: f (x@('a':_):_:zs) = x : f zs f (x:ys) = x : f ys f [] = [] Not obviously better, not obviously worse.
- uryga 10y agoThanks, I get it now! I know how guards work, I've just never seen a construct like `('a':_) <- x` (and misunderstood the task a bit :). My understanding is, that's basically inline do-notation, is that correct?. On a sidenote. I've seen code like `f (x:ys) = x : f ys` many times, for example in definitions of map or filter. It always seemed to me like we're wasting a lot of breath typing that - deconstructing the list with pattern matching, then reassembling it again, slightly changed. I feel like there's a general pattern here that could be factored out, do you know of anything like that?
- dllthomas 10y ago> My understanding is, that's basically inline do-notation, is that correct?. Not really. They're superficially similar, but translate differently. Do-notation desugars `x <- y` to `y >>= \ x -> ...`, whereas the pattern guard is more like 'case y of x -> ...; _ -> ...'. Most importantly, there is not necessarily any monad involved for pattern guards - `5 <- 5` is legitimate. `5 <- 5` is nonsensical in do notation (without some awfully weird instance of `Num`). > On a sidenote. I've seen code like `f (x:ys) = x : f ys` many times, for example in definitions of map or filter. It always seemed to me like we're wasting a lot of breath typing that - deconstructing the list with pattern matching, then reassembling it again, slightly changed. I feel like there's a general pattern here that could be factored out, do you know of anything like that? The general pattern, for map and filter, is a fold. Prelude Test.QuickCheck> let map' f = foldr (\ x -> (f x:)) [] Prelude Test.QuickCheck> let filter' f = foldr (\ x -> if f x then (x:) else id) [] Prelude Test.QuickCheck> quickCheck $ \ (Blind f, xs) -> map f xs == map' f xs +++ OK, passed 100 tests. Prelude Test.QuickCheck> Prelude Test.QuickCheck> quickCheck $ \ (Blind f, xs) -> filter f xs == filter' f xs +++ OK, passed 100 tests.