Making the type of a function depend on input - function

So I noticed that after n=20 the factorial function given in LearnYouAHaskell (below) craps out because of the finite work range of the Int type.
factorial :: Int -> Int
factorial 0 = 1
factorial n * factorial (n-1)
Using factorial :: Integer -> Integer fixes the issue nicely, but it brought to mind the question. Supposedly Integer is slightly slower than Int so ideally (and I know I'm pinching pennies here) I'd want my factorial function to only resort to Integer when the input is greater than 20 and retain the Int->Int type for the smaller numbers. Seems like there should be an elegant solution for this using if-then-else or guards, but keep running into syntactic pepper (error messages)

You can make a hackish solution without dependent types by using either a sum type and growing when needed or delaying the cast to Integer till the end in some cases. I don't expect either solution would perform better than using Integer - do not fear the Integer, gmp and mpir are quite good.
The casting solution is something like:
selectiveFactorial :: Integer -> Integer
selectiveFactorial i
| i < 20 = fromIntegral $ factorial (fromIntegral i :: Int)
| otherwise = factorial i
factorial :: Integral a => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)

As Rein Henrichs said you could do these things in a language with dependent types, which Haskell does not (yet, quite) have. In Idris, say, it would look something like
factorial : (n : Int) -> if n <= 20 then Int else Integer
factorial n with (n <= 20)
factorial n | True = thisfactorial n
factorial n | False = thatfactorial n
But how will you use this result? Well, you'll need to do the comparison to figure out what type to expect, and when all is said and done, I don't see how you've won anything. For completeness, the use site could look something like this:
use : Int -> Integer
use n with (factorial n)
use n | fn with (n <= 20)
use n | fn | False = fn
use n | fn | True = cast fn
Note that the order of the with clauses is significant! The fn binding gets type if n <= 20 then Int else Integer; for reasons I don't entirely understand, the n <= 20 test must be to the right of that in order for the pattern match to affect its type.

It can't be done. There are things you can do however:
Make the type more generic: factorial :: Num a => a -> a;
This allows the user of your function to decide what runtime penalties he wants to occur vs. what range of numbers is permissible.
Use a sum type like data PossiblyBig = Small Int | Big Integer, and then have an implementation instance Num PossiblyBig that encodes things that fit into Int as Small, and things that don't fit as Big; AFAIK Integer already works like that (look up the GMP implementation if you want to know for sure), so this is more of a general example than advice as to what you should do in this particular situation.

Making the type of a function depend on its values is exactly what dependent types are for. Unfortunately, Haskell does not have dependent types so this cannot be done.

Related

In SQL - how can I count the number of times Bit(0), Bit(1), ... Bit(N) are high for a decimal number?

I am dealing with a table of decimal values that represent binary numbers. My goal is to count the number of times Bit(0), Bit(1),... Bit(n) are high.
For example, if a table entry is 5 this converts to '101' which can be done using the BIN() function.
What I would like to do is increment a variable 'bit0Count' and 'bit2Count'
I have looked into the BIT_COUNT() function however this would only return 2 for the above example.
Any insight would be greatly appreciated.
SELECT SUM(n & (1<<2) > 0) AS bit2Count FROM ...
The & operator is a bitwise AND.
1<<2 is a number with only 1 bit set, left-shifted by two places, so it is binary 100. Using bitwise AND against you column n is either binary 100 or binary 000.
Testing that with > 0 returns either 1 or 0, since in MySQL, boolean results are literally the integers 1 for true and 0 for false (note this is not standard in other implementations of SQL).
Then you can SUM() these 1's and 0's to get a count of the occurrences where the bit was set.
To tell if bit N is set, use 1 << N to create a mask for that bit and then use bitwise AND to test it. So (column & (1 << N)) != 0 will be 1 if bit N is set, 0 if it's not set.
To total these across rows, use the SUM() aggregation function.
If you need to do this frequently, you could define a stored function:
CREATE FUNCTION bit_set(UNSIGNED INT val, TINYINT which) DETERMINISTIC
RETURN (val & (1 << which)) != 0;

Convert string to int in MySQL

I have a column with names like:
Ernest Hemingway
Jackson Pollock
I want to convert them to numbers and store them in an INT field. Maybe getting the position of each letter in the alphabet or something like this, resulting a number:
23764283456
23984623746
Is there any function to do something like this? I don't mind the length of the INT or if the result is one number or another. The important thing is that every time I apply the function to a name, the result is the same.
Thanks!
Try this:
crc32('Ernest Hemingway');
will always give you 2479642411
as #Gordon_Linoff said in the comments large number can't be store on filed of type int
but I will show you how to convert string to the ascii of the chars
you can use HEX
SELECT HEX('test')
+-------------+
| HEX('test') |
+-------------+
| 74657374 |
+-------------+
This is a one-way hash, but with an important concern: the integer should be representable on the platform.
PHP code, assuming 32-bit compatibility is desired:
$hash = sha1('Ernest Hemingway');
// last 6 characters, represent 3 bytes
$hash = substr($hash, -6);
$result = hexdec($hash); // integer: 1331016
Keep in mind this has a very low entropy: 2^24 = 16777216 possibilities
4 bytes is too large, because signed/unsigned integer discrepancies would lead to float with some inputs, and floats really can't be casted to integers with perfect determinism.
SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;

Polynomial-time logic puzzle using AND/OR/NOT to create <= on N inputs?

So let's say you have n boolean inputs of x1, x2, x3, ..., xn. How do you determine that <= k of your boolean inputs are True using only And/Or/Not logic gates, and doing so in polynomial time?
I'm quite honestly befuddled.
There are many ways to do it. One is to (recursively) make two nets:
one (A) determining that <= k-1 of boolean inputs x1 ... x[n-1] are True.
another (B) determining that <= k of boolean inputs x1 ... x[n-1] are True.
Connect them as (B And Not x[n]) Or A

Binary math on Number objects limited to 32 bits?

Consider the following code:
var combined:Number = Number(4294967296) | Number(2403025069);
var testLimit:Number = 6697992365;
trace("Combined is:", combined, "should be", testLimit);
Output is:
Combined is: -1891942227 should be 6697992365
Why?! I thought Number datatypes can hold 64 bit integers (okay- really 52-bit, but the numbers above are nowhere near that limit)
From the documentation:
| bitwise OR Operator
Converts expression1 and expression2 to 32-bit unsigned integers, and places a 1 in each bit position where the corresponding bits of either expression1 or expression2 are 1.
...
The result is interpreted as a 32-bit two's complement number, so the result is an integer in the range -2147483648 to 2147483647.

A homework about growth rate of function

Please order the function belows by growth rate
n ^ 1.5
n ^ 0.5 + log n
n log ^ 2 n
n log ( n ^ 2 )
n log log n
n ^ 2 + log n
n log n
n
ps:
Ordering by growth rate means, as n gets larger and larger, which function will eventually be higher in value than the others.
ps2. I have ordered most of the functions:
n , n log log n, n log n, n log^2 n, n log ( n ^ 2 ), n ^ 1.5
I just do not know how to order:
n ^ 2 + log n,
n ^ 0.5 + log n,
these 2 values
Can anyone help me?
Thank you
You can figure this out fairly easily by graphing the functions and seeing which ones get larger (find a graphing calculator, check out Maxima, or try graphing the functions on Wolfram Alpha). Or, or course, you just pick some large value of n and compare the various functions, but graphs can give a bit of a better picture.
The key to the answer you seek is that when you sum two functions, their combined "growth rate" is going to be exactly that of the one with the higher growth rate of the two. So, you now know the growth rates of these two functions, since you appear (from knowing the correct ordering of all the others) to know the proper ordering of the growth rates that are in play here.
Plugging in a large number is not the correct way to approach this!
Since you have the order of growth, then you can use the following rules http://faculty.ksu.edu.sa/Alsalih/CSC311_10_11_01/3.3_GrowthofFunctionsAndAsymptoticNotations.pdf
In all of those cases, you're dealing with pairs of functions that themselves have different growth rates.
With that in mind, only the larger one really matters, since it will be most dominant even with a sum. So in each of those function sums, which is the bigger one and how does it compare to the other ones on your larger list?
If you need to proof mathematically, you should try something like this.
If you have two functions, e.g.:
f1(n) = n log n
f2(n) = n
You can simply find the limit of f3(n) = f1(n)/f2(n) when n tends to infinity.
If the result is zero, then f2(n) has a greater growth rate than f1(n).
On the other hand, if the result is infinity then f1(n) has a greater growth rate than f2(n).
n0.5 (or n1/2) is the square root of n. So, it grows more slowly than n2.
let say n = 4 then we get
n ^ 2 + log n = 16.6020599913
n ^ 1.5 = 8
n = 4
n log ( n ^ 2 ) = 4.81
n ^ 0.5 + log n = 2.60205999133
n log n = 2.4
n log ^ 2 n = ?
n log log n = -0.8