Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are hashes (#) used for in the library's source?

Tags:

haskell

I was trying to figure out how mVars work, and I came across this bit of code:

-- |Create an 'MVar' which is initially empty.
newEmptyMVar  :: IO (MVar a)
newEmptyMVar = IO $ \ s# ->
    case newMVar# s# of
         (# s2#, svar# #) -> (# s2#, MVar svar# #)

Besides being confusingly mutually recursive with newMVar, it's also littered with hashs (#).

Between the two, I can't figure out how it works. I know that this is basically just a pseudo-constructor for mVar, but the rest of the module (most of the library actually) contains them, and I can't find anything on them. Googling "Haskell hashs" didn't yield anything relevant.

like image 967
Carcigenicate Avatar asked Oct 02 '14 21:10

Carcigenicate


People also ask

What are hashes used for?

Hashing is a cryptographic process that can be used to validate the authenticity and integrity of various types of input. It is widely used in authentication systems to avoid storing plaintext passwords in databases, but is also used to validate files, documents and other types of data.

What is a hash in cyber security?

Hashing is the practice of using an algorithm to map data of any size to a fixed length. This is called a hash value (or sometimes hash code or hash sums or even a hash digest if you're feeling fancy). Whereas encryption is a two-way function, hashing is a one-way function.

What are hashes in Crypto?

Key Takeaways. A hash is a function that meets the encrypted demands needed to solve for a blockchain computation. Hashes are of a fixed length since it makes it nearly impossible to guess the length of the hash if someone was trying to crack the blockchain. The same data will always produce the same hashed value.

What is meant by hashes?

Hashing is the process of transforming any given key or a string of characters into another value. This is usually represented by a shorter, fixed-length value or key that represents and makes it easier to find or employ the original string. The most popular use for hashing is the implementation of hash tables.


1 Answers

They're (literally) magic hashes. They distinguish GHC's primitive's like addition, unboxed types, and unboxed tuples. You can enable writing them with

{-# LANGUAGE MagicHash #-}

Now you can import the stubs that let you use them with

import GHC.Exts

unboxed :: Int# -> Int# -> Int#
unboxed a# b# = a# +# b#

boxed :: Int -> Int -> Int
boxed (I# a#) (I# b#) = I# (unboxed a# b#)

This actually is kinda nifty when you think about it, by wrapping the magical and strict primitives like this, we can handle lazy Ints and Chars uniformly at the runtime system level.

Because primitives are not boxed, they're segregated at the kind level. This means that Int# doesn't have the kind * like normal types, which also means something like

kindClash :: Int# -> Int#
kindClash = id -- id expects boxed types

Won't compile.

To further elaborate on your code, newMVar includes a call to a compiler primitive in GHC to allocate a new mutable variable. It's not mutually recursive so much as a thin wrapper over a compiler call. There's also some darkness gathering at the corners of this function since we're treating IO as a perverse state monad, but let's not look to closely at that. I like my sanity too much.

I don't use primitives in everyday code, nor should you. They come up when implementing crazy optimized hotspots, or near primitive abstractions like what you're looking at.

like image 75
Daniel Gratzer Avatar answered Oct 02 '22 10:10

Daniel Gratzer