4 ms·
> map parse . filter (not . startsWith "a") Almost! You have to skip two lines.
by hskl 10y ago
> map parse . filter (not . startsWith "a")
Almost! You have to skip two lines.
- wyager 10y agoTrue. OK, let's start with the OP's goal, not his code (which appears to have been consistently incorrect, conveniently and humorously contradicting his intended point). > The goal is to skip the line after a line starting with the letter "a". OK, so we want the following: ["x", "y", "a", "skip", "z"] -> ["x", "y", "a", "z"] Here's a non-clever but still more elegant (and correct) way: f (x:y:zs) | ('a':_) <- x = x : f zs | otherwise = x : f (y : zs) f zs = zs I guarantee you that there are multiple zippy one-liners that do the same thing, but I'll leave it at that for now. It's already a huge improvement, and does what it purports to!
- 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.