Assume you have 2 Integer Variables a and b
How would you swap them only if a > b by using a match expression?
If a <= b do not swap the ints.
In an imperative language:
if (a > b){
int temp=a;
a=b;
b=temp;
}
Doing the same in ocaml seems surprisingly hard.
I tried
let swap a b =
match a,b with
| a,b when a > b -> b,a
| a,b when a <= b -> a,b
I am trying to do this because in the following function call, I want to make sure that x is the bigger of the two variables.
One easy way :
let swap a b =
if (a>b) then (b,a)
else (a,b)
But this is not equivalent to the C code, your C code is swapping the value of the variable - this is how imperative language are doing.
In Ocaml, there is no side-effect (except if you use reference to some int). This swap function will return a tuple whose members are always ordered (the first member will be always smaller than the second order).
Without state, you cannot "swap" the values of the variables since the variables are immutable. Your best bet is to use a tuple and introduce new variables in the scope. Example:
let diff a b =
let (min, max) = if a <= b then (a, b) else (b, a)
in max - min
You can of course use the same identifiers and shadow the original variables:
let diff a b =
let (a, b) = if a <= b then (a, b) else (b, a)
in b - a
It doesn't really help with readability though.
Just for reference, if you'd like to swap the values in two refs, it would look like the following:
let swap a_ref b_ref =
let a, b = !a_ref, !b_ref in
a_ref := b;
b_ref := a
;;
which has the type val swap : 'a ref -> 'a ref -> unit.
Related
There might exist dialect specific ways, or maybe a general one. I have two dictionaries, let's say:
a := {'a' -> 1} asDictionary.
b := {'b' -> 2} asDictionary.
Now I want to get c as the union of a and b.
It depends on whether you want a third object or you prefer to include, say b, into a.
For the first case
c := Dictionary new.
a keysAndValuesDo: [:k :v | c at: k put: v].
b keysAndValuesDo: [:k :v | c at: k put: v].
For the second
b keysAndValuesDo: [:k :v | a at: k put: v].
Note also that the operation is not commutative, meaning that if the same key occurs in both dictionaries, the one that will survive in the result is the last added.
In Squeak/Pharo you can simply use union:
a := {'a' -> 1} as: Dictionary.
b := {'b' -> 2} as: Dictionary.
c := a union: b.
-> a Dictionary('a'->1 'b'->2 )
Note that the elements of b will be chosen in case of overlapping keys
a := {'a' -> 1. 'c'->0} as:Dictionary.
b := {'b' -> 2. 'c'->7} as:Dictionary.
c := a union: b.
-> a Dictionary('a'->1 'b'->2 'c'->7 )
Another one:
Dictionary new addAll: a; addAll: b; yourself
Also works when a and b are other collections of Associations, as in your question without asDictionary. Works at least in Squeak.
As pointed out by #aka.nice in the comments, depending on your Smalltalk implementation it may have the side effect of sharing the Association objects with the input dictionaries. It certainly is that way in Squeak. If a and b have common keys, it may even modify one of the input dictionaries (in Squeak a) because first an existing Association is added to the new Dictionary's hashtable, and then this Association gets the value from the other input Dictionary assigned.
a := Dictionary newFrom: {#a -> 1}.
b := Dictionary newFrom: {#a -> 2}.
c := Dictionary new addAll: a; addAll: b; yourself.
{a at: #a. b at: #a. c at: #a} "==> #(2 2 2) in Squeak"
c := a, b works in Pharo (but not in Dolphin)
I think Leandro's and aka.nice's answer provide you with nice solutions. Both also mention that you are going to lose information when the key is same for both of the dictionaries.
I'm writing this in order to complement these answers. If you should need to keep the duplicate key -> value I would do it the following way:
a := {'a' -> 1. 'c'->3} as: Bag.
b := {'b' -> 2. 'c'->20} as: Bag.
c := a union: b.
Which will give you a Bag with Dictionary as contents:
Dictionary('b'->2->1 'a'->1->1 'c'->20->1 'c'->3->1)
(I'm using Smalltalk/X-jv)
In attempting to learn Ocaml and functional languages in general, I have been looking into pattern matching. I was reading this documentation, and decided to try the following exercise for myself:
Make an expression that evaluates to true when an integer 4-tuple is input such that each element in the 4-tuple is equal.
(4, 4, 4, 4) -> true
(4, 2, 4, 4) -> false
I find that doing pattern matching for the specificity of the value of the elements to not be obvious. This is the code I wrote.
let sqr x = match x with
(a, a, a, a) -> true
| (_, _, _, _) -> false ;;
Of course, this code throws the following error:
Error: Variable a is bound several times in this matching
How else can I not only enforce that x is a 4-tuple, but also of strictly integers that are equal?
(Also, of course a "square" tuple should not allow non-positive integers, but I'm more concerned with the aforementioned problem as of now).
`
As you found out, unlike some other languages' pattern-matching systems, you can't do this in OCaml. What you can do is match each element of the tuple separately while using guards to only succeed if some property (like equivalence) holds across them:
let sqr x =
match x with
| (a, b, c, d) when a = b && b = c && c = d -> `Equal
| (a, b, c, d) when (a < b && b < c && c < d)
|| (a > b && b > c && c > d) -> `Ordered
| _ -> `Boring
You have many ways to do pattern-matching, pattern matching is not only when using the match keyword
let fourtuple_equals (a,b,c,d) = List.for_all ((=) a) [b;c;d]
val fourtuple_equals : 'a * 'a * 'a * 'a -> bool = <fun>
Here you have a pattern matching directly in the parameter in order to access your four elements tuple.
In this example I use a list to have a more concise code, but is not the more efficient.
Code:
let ab = let a = 'a' in let b = 'B' in (Char.lowercase b) in a :: [b];;
I am learning the let keyword. I want the expression to evaluate to the list of characters ['a', 'b'] but instead I keep getting the error
Error: Unbound value a
I don't know why this is happening. As far as I understand, I can keep using let inside let to create new bindings and I have used let to bind a to 'a' in the beginning itself and hence it should have a valid value in the inner scope as well right?
I know that I can simply do b = 'b' instead of b = 'B' in (Char.lowercase b) but I am experimenting with what I can do and what I cannot do and to me this should also work.
You have too many in keywords. The topmost let shouldn't have a corresponding in.
let ab =
let a = 'a' in
let b = 'B' in
(Char.lowercase b) in
a :: [b];;
Re-write it like this:
let ab =
let a = 'a' in
let b = 'B' in
a :: [Char.lowercase b];;
In fact, since the let b expression doesn't refer to a, you can write it like this:
let ab =
let a = 'a'
and b = 'B' in
a :: [Char.lowercase b];;
Based on discussion in comments, I would also suggest, if you want an expression:
let ab =
let a = 'a' in
let b = 'B' in
a::[Char.lowercase b]
in
(* The rest of your code. *)
The problem is that your expression was this:
let ab =
let a = 'a' in
let b = 'B' in
Char.lowercase b (* Result: ab gets bound to 'b'. *)
in
a :: [b] (* a and b aren't visible out here! *)
I also recommend indenting in a style similar to this one, to help you see such things clearly. OCaml programmers usually break lines before let. If you have let p = e in e' and e or e' don't fit on one line, indent the e, but not the e'. That way, you can quickly see which further expressions the bindings of p are visible in, and see that any bindings made in e are not visible in e'.
Short Question: What is the importance of isomorphic functions in programming (namely in functional programming)?
Long Question: I'm trying to draw some analogs between functional programming and concepts in Category Theory based off of some of the lingo I hear from time-to-time. Essentially I'm trying to "unpackage" that lingo into something concrete I can then expand on. I'll then be able to use the lingo with an understanding of just-what-the-heck-I'm-talking about. Which is always nice.
One of these terms I hear all the time is Isomorphism, I gather this is about reasoning about equivalence between functions or function compositions. I was wondering if someone could provide some insights into some common patterns where the property of isomorphism comes in handy (in functional programming), and any by-products gained, such as compiler optimizations from reasoning about isomorphic functions.
I take a little issue with the upvoted answer for isomorphism, as the category theory definition of isomorphism says nothing about objects. To see why, let's review the definition.
Definition
An isomorphism is a pair of morphisms (i.e. functions), f and g, such that:
f . g = id
g . f = id
These morphisms are then called "iso"morphisms. A lot of people don't catch that the "morphism" in isomorphism refers to the function and not the object. However, you would say that the objects they connect are "isomorphic", which is what the other answer is describing.
Notice that the definition of isomorphism does not say what (.), id, or = must be. The only requirement is that, whatever they are, they also satisfy the category laws:
f . id = f
id . f = f
(f . g) . h = f . (g . h)
Composition (i.e. (.)) joins two morphisms into one morphism and id denotes some sort of "identity" transition. This means that if our isomorphisms cancel out to the identity morphism id, then you can think of them as inverses of each other.
For the specific case where the morphisms are functions, then id is defined as the identity function:
id x = x
... and composition is defined as:
(f . g) x = f (g x)
... and two functions are isomorphisms if they cancel out to the identity function id when you compose them.
Morphisms versus objects
However, there are multiple ways two objects could be isomorphic. For example, given the following two types:
data T1 = A | B
data T2 = C | D
There are two isomorphisms between them:
f1 t1 = case t1 of
A -> C
B -> D
g1 t2 = case t2 of
C -> A
D -> B
(f1 . g1) t2 = case t2 of
C -> C
D -> D
(f1 . g1) t2 = t2
f1 . g1 = id :: T2 -> T2
(g1 . f1) t1 = case t1 of
A -> A
B -> B
(g1 . f1) t1 = t1
g1 . f1 = id :: T1 -> T1
f2 t1 = case t1 of
A -> D
B -> C
g2 t2 = case t2 of
C -> B
D -> A
f2 . g2 = id :: T2 -> T2
g2 . f2 = id :: T1 -> T1
So that's why it's better to describe the isomorphism in terms of the specific functions relating the two objects rather than the two objects, since there may not necessarily be a unique pair of functions between two objects that satisfy the isomorphism laws.
Also, note that it is not sufficient for the functions to be invertible. For example, the following function pairs are not isomorphisms:
f1 . g2 :: T2 -> T2
f2 . g1 :: T2 -> T2
Even though no information is lost when you compose f1 . g2, you don't return back to your original state, even if the final state has the same type.
Also, isomorphisms don't have to be between concrete data types. Here's an example of two canonical isomorphisms are not between concrete algebraic data types and instead simply relate functions: curry and uncurry:
curry . uncurry = id :: (a -> b -> c) -> (a -> b -> c)
uncurry . curry = id :: ((a, b) -> c) -> ((a, b) -> c)
Uses for Isomorphisms
Church Encoding
One use of isomorphisms is to Church-encode data types as functions. For example, Bool is isomorphic to forall a . a -> a -> a:
f :: Bool -> (forall a . a -> a -> a)
f True = \a b -> a
f False = \a b -> b
g :: (forall a . a -> a -> a) -> Bool
g b = b True False
Verify that f . g = id and g . f = id.
The benefit of Church encoding data types is that they sometimes run faster (because Church-encoding is continuation-passing style) and they can be implemented in languages that don't even have language support for algebraic data types at all.
Translating Implementations
Sometimes one tries to compare one library's implementation of some feature to another library's implementation, and if you can prove that they are isomorphic, then you can prove that they are equally powerful. Also, the isomorphisms describe how to translate one library into the other.
For example, there are two approaches that provide the ability to define a monad from a functor's signature. One is the free monad, provided by the free package and the other is operational semantics, provided by the operational package.
If you look at the two core data types, they look different, especially their second constructors:
-- modified from the original to not be a monad transformer
data Program instr a where
Lift :: a -> Program instr a
Bind :: Program instr b -> (b -> Program instr a) -> Program instr a
Instr :: instr a -> Program instr a
data Free f r = Pure r | Free (f (Free f r))
... but they are actually isomorphic! That means that both approaches are equally powerful and any code written in one approach can be translated mechanically into the other approach using the isomorphisms.
Isomorphisms that are not functions
Also, isomorphisms are not limited to functions. They are actually defined for any Category and Haskell has lots of categories. This is why it's more useful to think in terms of morphisms rather than data types.
For example, the Lens type (from data-lens) forms a category where you can compose lenses and have an identity lens. So using our above data type, we can define two lenses that are isomorphisms:
lens1 = iso f1 g1 :: Lens T1 T2
lens2 = iso g1 f1 :: Lens T2 T1
lens1 . lens2 = id :: Lens T1 T1
lens2 . lens1 = id :: Lens T2 T2
Note that there are two isomorphisms in play. One is the isomorphism that is used to build each lens (i.e. f1 and g1) (and that's also why that construction function is called iso), and then the lenses themselves are also isomorphisms. Note that in the above formulation, the composition (.) used is not function composition but rather lens composition, and the id is not the identity function, but instead is the identity lens:
id = iso id id
Which means that if we compose our two lenses, the result should be indistinguishable from that identity lens.
An isomorphism u :: a -> b is a function that has an inverse, i.e. another function v :: b -> a such that the relationships
u . v = id
v . u = id
are satisfied. You say that two types are isomorphic if there is an isomorphism between them. This essentially means that you can consider them to be the same type - anything that you can do with one, you can do with the other.
Isomorphism of functions
The two function types
(a,b) -> c
a -> b -> c
are isomorphic, since we can write
u :: ((a,b) -> c) -> a -> b -> c
u f = \x y -> f (x,y)
v :: (a -> b -> c) -> (a,b) -> c
v g = \(x,y) -> g x y
You can check that u . v and v . u are both id. In fact, the functions u and v are better known by the names curry and uncurry.
Isomorphism and Newtypes
We exploit isomorphism whenever we use a newtype declaration. For example, the underlying type of the state monad is s -> (a,s) which can be a little confusing to think about. By using a newtype declaration:
newtype State s a = State { runState :: s -> (a,s) }
we generate a new type State s a which is isomorphic to s -> (a,s) and which makes it clear when we use it, we are thinking about functions that have modifiable state. We also get a convenient constructor State and a getter runState for the new type.
Monads and Comonads
For a more advanced viewpoint, consider the isomorphism using curry and uncurry that I used above. The Reader r a type has the newtype declaration
newType Reader r a = Reader { runReader :: r -> a }
In the context of monads, a function f producing a reader therefore has the type signature
f :: a -> Reader r b
which is equivalent to
f :: a -> r -> b
which is one half of the curry/uncurry isomorphism. We can also define the CoReader r a type:
newtype CoReader r a = CoReader { runCoReader :: (a,r) }
which can be made into a comonad. There we have a function cobind, or =>> which takes a function that takes a coreader and produces a raw type:
g :: CoReader r a -> b
which is isomorphic to
g :: (a,r) -> b
But we already saw that a -> r -> b and (a,r) -> b are isomorphic, which gives us a nontrivial fact: the reader monad (with monadic bind) and the coreader comonad (with comonadic cobind) are isomorphic as well! In particular, they can both be used for the same purpose - that of providing a global environment that is threaded through every function call.
Think in terms of datatypes. In Haskell for example you can think of two data types to be isomorphic, if there exists a pair of functions that transform data between them in a unique way. The following three types are isomorphic to each other:
data Type1 a = Ax | Ay a
data Type2 a = Blah a | Blubb
data Maybe a = Just a | Nothing
You can think of the functions that transform between them as isomorphisms. This fits with the categorical idea of isomorphism. If between Type1 and Type2 there exist two functions f and g with f . g = g . f = id, then the two functions are isomorphisms between those two types (objects).
Are there hashtables in Ocaml that use == instead of = when testing for equality of keys?
For example:
# type foo = A of int;;
# let a = A(1);;
# let b = A(1);;
# a == b;;
- : bool = false
# a = b;;
- : bool = true
# let h = Hashtbl.create 8;;
# Hashtbl.add h a 1;;
# Hashtbl.add h b 2;;
# Hashtbl.find h a;;
- : int = 2
# Hashtbl.find h b;;
- : int = 2
I'd like a hashtable that can distinguish between a and b. Is that possible?
You can use custom hashtables:
module H = Hashtbl.Make(struct
type t = foo
let equal = (==)
let hash = Hashtbl.hash
end)
And then use H instead of Hashtbl in your code.
The solution in Thomas and cago's answers is functionally correct. One issue that may trouble you if you use their solution as-is is that you will get more collisions than expected if you hash many keys that are equal for (=) and different for (==). Indeed, all keys that are equal for (=) have the same hash for Hashtbl.hash, and end up in the same bucket, where they are they recognized as different (since you asked for (==) to be used as equality function) and create different bindings. In the worst cases, the hash-table will behave with the same complexity as an association list (which, by the way, is another data structure that you could be using, and then you wouldn't have to worry about providing a hash function).
If you can accept the key of a value changing occasionally (and therefore the value being impossible to retrieve from the hash-table, since the binding is then in the wrong bucket), you can use the following low-level function as hash:
external address_of_value: 'a -> int = "address_of_value"
Implemented in C as:
#include "caml/mlvalues.h"
value address_of_value(value v)
{
return (Val_long(((unsigned long)v)/sizeof(long)));
}
You would then use:
module H = Hashtbl.Make(struct
type t = foo
let equal = (==)
let hash = address_of_value
end);;