Recovering nat from a positive integer in Lean - lean

Given (a : Z) and (a >= 0), I would like to have (n : N) such that n = a. This is of course a bit troublesome because n = a is heterogeneous equality.
I have found nat_abs which does something like this except it also handles the case when I have a negative whole number, which I know that I don't.
How does one deal with this situation in Lean?

n = a isn't a heterogeneous equality, since you (hopefully) can't prove N = Z. The best you can hope for is int.of_nat n = a, and you should be able to prove from a >= 0 that int.of_nat (nat_abs a) = a.
Note that you can write a = n, and it will type check, because Lean will coerce n to int.of_nat n. This is not a heterogeneous equality, it's a normal equality in Z.

Related

Why can't you use 'Just' syntax without 'let..in' block in Haskell?

I have a few questions regarding the Just syntax in Haskell.
When question arose when I was experimenting with different ways to write a function to calculate binomial coefficients.
Consider the function:
binom :: Integer -> Integer -> Maybe Integer
binom n k | n < k = Nothing
binom n k | k == 0 = Just 1
binom n k | n == k = Just 1
binom n k | otherwise = let
Just x = (binom (n-1) (k-1))
Just y = (binom (n-1) k)
in
Just (x + y)
When I try to write the otherwise case without the let..in block without the let..in block like so:
binom n k | otherwise = (binom (n-1) (k-1)) + (binom (n-1) k)
I am faced with a compilation error No instance for (Num (Maybe Integer)) arising from a use of ‘+’. And so my first thought was that I was forgetting the Just syntax so I rewrote it as
binom n k | otherwise = Just ((binom (n-1) (k-1)) + (binom (n-1) k))
I am faced with an error even more confusing:
Couldn't match type ‘Maybe Integer’ with ‘Integer’
Expected: Maybe Integer
Actual: Maybe (Maybe Integer)
If I add Just before the binom calls, the error just compounds:
Couldn't match type ‘Maybe (Maybe Integer)’ with ‘Integer’
Expected: Maybe Integer
Actual: Maybe (Maybe (Maybe Integer))
Furthermore, if I write:
Just x = binom 3 2
y = binom 3 2
x will have the value 3 and y will have the value Just 3.
So my questions are:
Why does the syntax requite the let..in block to compile properly?
In the function, why does Just add the Maybe type when I don't use let..in?
Contrarily, why does using Just outside of the function remove the Just from the value if it's type is Just :: a -> Maybe a
Bonus question, but unrelated:
When I declare the function without the type the compiler infers the type binom :: (Ord a1, Num a2, Num a1) => a1 -> a1 -> Maybe a2. Now I mostly understand what is happening here, but I don't see why a1 has two types.
Your question demonstrates a few ways you may have got confused about what is going on.
Firstly, Just is not any kind of syntax - it's just a data constructor (and therefore also a function) provided by the standard library. The reasons your failing attempts didn't compile are therefore not due to any syntax mishaps (the compiler would report a "parse error" in this case), but - as it actually reports - type errors. In other words the compiler is able to parse the code to make sense of it, but then when checking the types, realises something is up.
So to expand on your failing attempts, #1 was this:
binom n k | otherwise = Just ((binom (n-1) (k-1)) + (binom (n-1) k))
for which the reported error was
No instance for (Num (Maybe Integer)) arising from a use of ‘+’
This is because you were trying to add the results of 2 calls to binom - which according to your type declaration, are values of type Maybe Integer. And Haskell doesn't by default know how to add two Maybe Integer values (what would Just 2 + Nothing be?), so this doesn't work. You would need to - as you eventually do with your successful attempt - unwrap the underlying Integer values (assuming they exist! I'll come back to this later), add those up, and then wrap the resulting sum in a Just.
I won't dwell on the other failing attempts, but hopefully you can see that, in various ways, the types also fail to match up here too, in the ways described by the compiler. In Haskell you really have to understand the types, and just flinging various bits of syntax and function calls about in the wild hope that the thing will finally compile is a recipe for frustration and lack of success!
So to your explicit questions:
Why does the syntax requite the let..in block to compile properly?
It doesn't. It just needs the types to match everywhere. The version you ended up with:
let
Just x = (binom (n-1) (k-1))
Just y = (binom (n-1) k)
in
Just (x + y)
is fine (from the type-checking point of view, anyway!) because you're doing as I previously described - extracting the underlying values from the Just wrapper (these are x and y), adding them up and rewrapping them.
But this approach is flawed. For one thing, it's boilerplate - a lot of code to write and try to understand if you're seeing it for the first time, when the underlying pattern is really simple: "unwrap the values, add them together, then rewrap". So there should be a simpler, more understandable, way to do this. And there is, using the methods of the Applicative typeclass - of which the Maybe type is a member.
Experienced Haskellers would write the above in one of two ways. Either:
binom n k | otherwise = liftA2 (+) (binom (n-1) (k-1)) (binom (n-1) k)
or
binom n k | otherwise = (+) <$> binom (n-1) (k-1) <*> binom (n-1) k
(the latter being in what is called the "applicative style" - if you're unfamiliar with Applicative functors there's a great introduction in Learn You a Haskell here. )
And there's another advantage of doing this compared to your way, besides the avoidance of boilerplate code. Your pattern matches in the let... in expression assume that the results of binom (n-1) (k-1) and so on are of the form Just x. But they could also be Nothing - in which case your program will crash at runtime! And exactly this will indeed happen in your case, as #chepner describes in his answer.
Using liftA2 or <*> will, due to how the Applicative instance is implemented for Maybe, avoid a crash by simply giving you Nothing as soon as one of the things you're trying to add is Nothing. (And this in turn means your function will always return Nothing - I'll leave it to you to figure out how to fix it!)
I'm not sure I really understand your questions #2 and #3, so I won't address those directly - but I hope this has given you some increased understanding of how to work with Maybe in Haskell. Finally for your last question, although it's quite unrelated: "I don't see why a1 has two types" - it doesn't. a1 denotes a single type, because it's a single type variable. You're presumably referring to the fact it has two constraints - here Ord a1 and Num a1. Ord and Num here are typeclasses - like Applicative is that I mentioned earlier (albeit Ord and Num are simpler typeclasses). If you don't know what a typeclass is I recommend reading an introductory source, like Learn You a Haskell, before continuing much further with the language - but in short it's a bit like an interface, saying that the type must implement certain functions. Concretely, Ord says the type must implement order comparisons - you need that here because you've used the < operator - while Num says you can do numeric things with it, like addition. So that type signature just makes explicit what is implicit in your function definition - the values you use this function on must be of a type that implements both order comparison and numeric operations.
binom n k | otherwise = (binom (n-1) (k-1)) + (binom (n-1) k)
You can't add two Maybe values, but you can make use of the Functor instance to add the values already wrapped in Just.
binom n k | otherwise = fmap (+) (binom (n-1) (k-1)) (binom (n-1) k)
This doesn't quite work, as eventually the recursive calls will return Nothing, and fmap (+) x y == Nothing if either x or y is Nothing. The solution is to treat two different occurrences of n < k differently.
An "initial" use can return Nothing
A "recursive" use can simply return 0, since x + 0 == x.
binom will be implemented in terms of a helper that is guaranteed to receive arguments such that n >= k.
binom :: Integer -> Integer -> Maybe Integer
binom n k | n < k = Nothing
| otherwise = Just (binom' n k)
where binom' n 0 = 1
binom' n k | n == k = 1
| otherwise = binom' (n-1) (k-1) + binom' (n-1) k
This question has received excellent answers. However, I think it is worth mentioning that you can also use a monadic do construct, like the one normally used for the “main program” of a Haskell application.
The main program generally uses a do construct within the IO monad. Here, you would use a do construct within the Maybe monad.
Your binom function can be modified like this:
binom :: Integer -> Integer -> Maybe Integer
binom n k | n < 0 = Nothing -- added for completeness
binom n k | k < 0 = Nothing -- added for completeness
binom n k | n < k = Nothing
binom n k | k == 0 = Just 1
binom n k | n == k = Just 1
binom n k | otherwise = do -- monadic do construct, within the Maybe monad
x <- (binom (n-1) (k-1))
y <- (binom (n-1) k)
return (x+y)
main :: IO ()
main = do -- classic monadic do construct, within the IO monad
putStrLn "Hello impure world !"
putStrLn $ show (binom 6 3)
If a single <- extractor fails, the whole result is Nothing.
Please recall that in that context, return is just an ordinary function, with type signature:
return :: Monad m => a -> m a
Unlike in most imperative languages, return is not a keyword, and is not part of control flow.
A key concern is that if you have many quantities that can become Nothing, the do construct looks more scalable, that is, it can become more readable than pattern matching or lift'ing functions. More details about using the Maybe monad in the online Real World Haskell book.
Note that the Haskell library provides not only liftA2, as mentioned in Robin Zigmond's answer, but also other lift'ing functions up to lift6.
Interactive testing:
You can test the thing under the ghci interpreter, like this:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
λ>
λ> do { n1 <- (Just 3) ; n2 <- (Just 42); return (n1+n2) ; }
Just 45
λ>
λ> do { n1 <- (Just 3) ; n2 <- (Just 42); n3 <- Nothing ; return (n1+n2+n3) ; }
Nothing
λ>
The exact semantics depend on the sort of monad involved. If you use the list monad, you get a Cartesian product of the lists you're extracting from:
λ>
λ> do { n1 <- [1,2,3] ; n2 <- [7,8,9]; return (n1,n2) ; }
[(1,7),(1,8),(1,9),(2,7),(2,8),(2,9),(3,7),(3,8),(3,9)]
λ>

Other data types interaction with own constructed Natural datatype

I've made my own data type constructed for the Natural Numbers.
data Natural = Zero | Succ Natural
instance Show Natural where
show (Zero) = "0"
show (Succ Zero) = "S 0"
show (Succ n) = "S(" ++ show n ++ ")"
I'm trying to make a function to interact with basic data types (mostly Int) defined as it follows:
intToNat:: Int -> Natural
intToNat 0 = Zero
intToNat n = (Succ n) - 1
natToInt:: Natural -> Int
natToInt Zero = 0
natToInt (Succ n) = 1 + natToInt n
Well, this doesn't work at all, the matter is, I must to keep this function as a recursive function. I don't know if the read function would be helpful on this.
UPDATE: A manner at how the code does compile is using in the function:
intToNat:: Int -> Natural
intToNat 0 = Zero
intToNat n = Succ(Succ Zero) --Obviusly this method return a constant number, in this case: 2.
So in this case, I guess is related, but I want to know if there is a 'recursive' way to define the 'loop' of Suc Zero n-1 times.
FINAL Update: The intToNat is defined as it follows:
intToNat:: Int -> Natural
intToNat 0 = Zero
intToNat n = Suc(intToNat (n-1))
natToInt looks OK. Zero, Succ n, and n all have type Natural. 1 and natToInt n has type Int. You call + on two Ints.
In inToNat, n has type Int, but Succ needs a Natural. You then try to subtract 1 from a Natural, but you have not defined - for Natural (at least, not in the code in your question). Your intToNat is not recursive, but you probably want it to be.
You are generally on the right track. read is not necessary.

Haskell - defining commutative functions: How to consider actual arguments by combination, not permutation

I want to define a function that considers it's equally-typed arguments without considering their order. For example:
weirdCommutative :: Int -> Int -> Int
weirdCommutative 0 1 = 999
weirdCommutative x y = x + y
I would like this function to actually be commutative.
One option is adding the pattern:
weirdCommutative 1 0 = 999
or even better:
weirdCommutative 1 0 = weirdCommutative 0 1
Now lets look at the general case: There could be more than two arguments and/or two values that need to be considered without order - So considering all possible cases becomes tricky.
Does anyone know of a clean, natural way to define commutative functions in Haskell?
I want to emphasize that the solution I am looking for is general and cannot assume anything about the type (nor its deconstruction type-set) except that values can be compared using == (meaning that the type is in the Eq typeclass but not necessarily in the Ord typeclass).
There is actually a package that provides a monad and some scaffolding for defining and using commutative functions. Also see this blog post.
In a case like Int, you can simply order the arguments and feed them to a (local) partial function that only accepts the arguments in that canonically ordered form:
weirdCommutative x y
| x > y = f y x
| otherwise = f x y
where f 0 1 = 999
f x' y' = x' + y'
Now, obviously most types aren't in the Ord class – but if you're deconstructing the arguments by pattern-matching, chances are you can define at least some partial ordering. It doesn't really need to be >.

Project euler problem 3 in haskell

I'm new in Haskell and try to solve 3 problem from http://projecteuler.net/.
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My solution:
import Data.List
getD :: Int -> Int
getD x =
-- find deviders
let deriveList = filter (\y -> (x `mod` y) == 0) [1 .. x]
filteredList = filter isSimpleNumber deriveList
in maximum filteredList
-- Check is nmber simple
isSimpleNumber :: Int -> Bool
isSimpleNumber x = let deriveList = map (\y -> (x `mod` y)) [1 .. x]
filterLength = length ( filter (\z -> z == 0) deriveList)
in
case filterLength of
2 -> True
_ -> False
I try to run for example:
getD 13195
> 29
But when i try:
getD 600851475143
I get error Exception: Prelude.maximum: empty list Why?
Thank you #Barry Brown, I think i must use:
getD :: Integer -> Integer
But i get error:
Couldn't match expected type `Int' with actual type `Integer'
Expected type: [Int]
Actual type: [Integer]
In the second argument of `filter', namely `deriveList'
In the expression: filter isSimpleNumber deriveList
Thank you.
Your type signature limits the integer values to about 2^29. Try changing Int to Integer.
Edit:
I see that you already realised that you need to use Integer instead of Int. You need to change the types of both getD and isSimpleNumber otherwise you will get a type mismatch.
Also in general, if you are having trouble with types, simply remove the type declarations and let Haskell tell you the correct types.
Main> :t getD
getD :: Integral a => a -> a
Main> :t isSimpleNumber
isSimpleNumber :: Integral a => a -> Bool
After you found the error, may I point out that your solution is quite verbose? In this case a very simple implementation using brute force is good enough:
getD n = getD' n 2 where
getD' n f | n == f = f
| n `mod` f == 0 = getD' (n `div` f) f
| otherwise = getD' n (succ f)
this question is easy enough for brute-force solution, but it is a bad idea to do so because the whole idea of project euler is problems you need to really think of to solve (see end of answer)
so here are some of your program's flaws:
first, use rem instead of mod. it is more efficient.
some mathematical thinking should have told you that you don't need to check all numbers from 1 to x in the isprime function and the getD function, but checking all numbers from the squareroot to one (or reversed) should be sufficient. note that in getD you will actually need to filter numbers between x and the square root, because you search for the biggest one.
why do you use the maximum function in getD? you know the list is monotonically growing, so you may as well get the last one.
despite you only need the biggest divisor (which is prime) you compute the divisors list from small to big making the computer check for each value if it is a divisor or not although discarding the result once a bigger divisor is found. it should be fixed by filtering the list of numbers from x to 1, not from 1 to x. this will cause the computer to check divisibility (how should I say that?) for the biggest possible divisor, not throwing to the trash the knowledge of previous checks. note that this optimization takes effect only if the previous point is optimized, because otherwise the computer will compute all divisors anyway.
with the previous points mixed, you should have filtered all numbers [x,x-1 .. squareroot x] and taken the first.
you don't use an efficient isPrime function. if I were you, I would have searched for an isprime library function, which is guaranteed to be efficient.
and there are more..
with this kind of code you will never be able to solve harder project euler problems. they are designed to need extra thinking about the problem (for instance noticing you don't have to check numbers greater from the square root) and writing fast and efficient code. this is the purpose of project euler; being smart about programming. so don't skip it.

If I have an expression, which is partitially evaluable, is it a good idea to avoid tail-recursion?

Consider an haskell-expression like the following: (Trivial example, don't tell me what the obvious way is! ;)
toBits :: Integral a => a -> [Bool]
toBits 0 = []
toBits n = x : toBits m where
(m,y) = n `divMod` 2
x = y /= 0
Because this function is not tail-recursive, one could also write:
toBits :: Integral a => a -> [Bool]
toBits = toBits' [] where
toBits' l 0 = l
toBits' l n = toBits (x : l) m where
(m,y) = n `divMod` 2
x = y /= 0
(I hope there is nothing wron whithin this expression)
What I want to ask is, which one of these solutions is better. The advantage of the first one is, that it can be evaluated partitially very easy (because Haskell stops at the first : not needed.), but the second solution is (obviously) tail-recursive, but in my opinion it needs to be completely evaluated until you can get something out.
The background for this is my Brainfuck parser, (see my optimization question), which is implemented very uggly (various reverse instructions... ooh), but can be implemented easily in the first - let's call it "semi-tail-recursion" way.
I think you've got it all just right. The first form is in general better because useful output can be obtained from it before it has completed computation. That means that if 'toBits' is used in another computation the compiler can likely combine them and the list that is the output of 'toBits' may never exist at all, or perhaps just one cons cell at a time. Nice that the first version is also more clear to read!
In Haskell, your first choice would typically be preferred (I would say "always," but you're always wrong when you use that word). The accumulator pattern is appropriate for when the output can not be consumed incrementally (e.g. incrementing a counter).
Let me rename the second version and fix a few typos so that you can test the functions.
toBits :: Integral a => a -> [Bool]
toBits 0 = []
toBits n = x : toBits m where
(m,y) = n `divMod` 2
x = y /= 0
toBits2 :: Integral a => a -> [Bool]
toBits2 = toBits' [] where
toBits' l 0 = l
toBits' l n = toBits' (x : l) m where
(m,y) = n `divMod` 2
x = y /= 0
These functions don't actually compute the same thing; the first one produces a list starting with the least significant bit, while the second one starts with the most significant bit. In other words toBits2 = reverse . toBits, and in fact reverse can be implemented with exactly the same kind of accumulator that you use in toBits2.
If you want a list starting from the least significant bit, toBits is good Haskell style. It won't produce a stack overflow because the recursive call is contained inside the (:) constructor which is lazy. (Also, you can't cause a thunk buildup in the argument of toBits by forcing the value of a late element of the result list early, because the argument needs to be evaluated in the first case toBits 0 = [] to determine whether the list is empty.)
If you want a list starting from the most significant bit, either writing toBits2 directly or defining toBits and using reverse . toBits is acceptable. I would probably prefer the latter since it's easier to understand in my opinion and you don't have to worry about whether your reimplementation of reverse will cause a stack overflow.

Resources