Remember lastLE? Back when we were trying to determine how many digits/bits it takes to represent a non-negative Integer, we used it to avoid copying a prefix of a list just to grab the value at its end.
lastLE :: Integer -> [Integer] -> Maybe (Integer, Int)
lastLE n xs =
let lastLE' xs prevVal prevIndex
| head xs <= n = lastLE' (tail xs) (head xs) (prevIndex + 1)
| otherwise = if prevIndex < 0 then Nothing
else Just (prevVal, prevIndex)
in lastLE' xs (-1) (-1)
It still bugs me. First, the mixed guards and if/else are less than idiomatic Haskell:
lastLE n xs =
let lastLE' xs prevVal prevIndex
| head xs <= n = lastLE' (tail xs) (head xs) (prevIndex + 1)
| prevIndex < 0 = Nothing
| otherwise = Just (prevVal, prevIndex)
in lastLE' xs (-1) (-1)
Second, the head and tail are clumsy:
lastLE n xs =
let lastLE' (x:xs) prevVal prevIndex
| x <= n = lastLE' xs x (prevIndex + 1)
| prevIndex < 0 = Nothing
| otherwise = Just (prevVal, prevIndex)
in lastLE' xs (-1) (-1)
Third, that accumulator should be strict, so pretend there's a ! in front of prevIndex in that let.
I think I'd rather see Nothing as the otherwise case.
lastLE n xs =
let lastLE' (x:xs) prevVal !prevIndex
| x <= n = lastLE' xs x (prevIndex + 1)
| prevIndex >= 0 = Just (prevVal, prevIndex)
| otherwise = Nothing
in lastLE' xs (-1) (-1)
Come to think of it, we can be consistent in our use of pairs:
lastLE n xs =
let lastLE' (x:xs) !prev@(val, index)
| x <= n = lastLE' xs (x, index + 1)
| prevIndex >= 0 = Just prev
| otherwise = Nothing
in lastLE' xs (-1, -1)
Now, one more thing. Can I get rid of the magic numbers there, the -1s? The -1 as initial index needs to be there to get the correct position in the list of powers of the base. The initial val will never be used. If the whole pair is strict, though, we couldn't pass in ⊥ ("bottom", the undefined value, which is undefined in Haskell). Perhaps
lastLE n xs =
let lastLE' (x:xs) prev@(val, !index)
| x <= n = lastLE' xs (x, index + 1)
| index >= 0 = Just prev
| otherwise = Nothing
in lastLE' xs (undefined, -1)
would be the way to go. Hey! We never even use that value here--it's used in the caller--so we can write
lastLE n xs =
let lastLE' (x:xs) prev@(_, !index)
| x <= n = lastLE' xs (x, index + 1)
| index >= 0 = Just prev
| otherwise = Nothing
in lastLE' xs (undefined, -1)
and it should work (sure enough, it does), as well as expressing explicitly that we don't use it. Well, that's one magic number down, at least.
random notes and thoughts, mostly about Haskell these days, of a rather past middle-aged programmer
Monday, August 05, 2013
Sunday, August 04, 2013
Small things...
Good grief... I've let this go for a month. (UPDATE: No, I haven't. It helps to read the dates carefully.)
An option in pattern matching that I wasn't fully aware of: you can use _ when you don't care about what is there, and have no need to refer to it. I guess I did use it on the ByteString readInteger that returns Maybe(Integer, ByteString):
process line = case map B.readInteger (B.words line) of
[Just (m, _), Just (n, _)] -> numXs m n
_ -> -1
But I didn't realize that I could use it in
ysInRange m n d
| nVal == n = nPos - mPos + 1
| otherwise = nPos - mPos
where (_, mPos) = findFirst' m
(nVal, nPos) = findFirst' n
findFirst' x = case findFirst (Ge x, Any) (dDigitYTree d) of
Just (Max i, Max j) -> (i, j)
Nothing -> (tenToThe d, numNDigitYs d)
because we need only check for an exact match at the high end.
An option in pattern matching that I wasn't fully aware of: you can use _ when you don't care about what is there, and have no need to refer to it. I guess I did use it on the ByteString readInteger that returns Maybe(Integer, ByteString):
process line = case map B.readInteger (B.words line) of
[Just (m, _), Just (n, _)] -> numXs m n
_ -> -1
But I didn't realize that I could use it in
ysInRange m n d
| nVal == n = nPos - mPos + 1
| otherwise = nPos - mPos
where (_, mPos) = findFirst' m
(nVal, nPos) = findFirst' n
findFirst' x = case findFirst (Ge x, Any) (dDigitYTree d) of
Just (Max i, Max j) -> (i, j)
Nothing -> (tenToThe d, numNDigitYs d)
because we need only check for an exact match at the high end.
Subscribe to:
Posts (Atom)
Riddler Classic, May 23, 2020—Holy Mackerel!
Another one using Peter Norvig's word list . It turns out that the word "mackerel" has a curious property: there is exactly ...
-
Back in the Cretaceous era I worked at the University of Oklahoma as a student assistant at Remote 1. OU was a [shudder] IBM big iron shop a...
-
You've probably heard about how the notion of sum types (e.g. Algol 68 union s, Rust enum s, Haskell type s) and product types (e.g. tup...
-
Verbal Abuse as Entertainment When I grew up, my parents always told me that there was a sort of person who needed to tear down others t...