Creating a Function Representation for Environments in SML - sml

Okay, So I am working on creating a function representation for environments in SML:
type name = string
type 'a fenv = name -> 'a
I'm a little stuck on how to proceed with this. The first thing I need to do is define a value fenvEmpty of type 'a fenv, which represents the empty environment (the environment that does not bind any names). So far, I have this:
val fenvEmpty =
let
fun empty (name) = ???
in
empty
end
I'm not sure if I'm on the right track or anything. What am I supposed to return from the function empty? Putting in 0, null, or NONE won't work.
Later, I also have to write functions that returns data associated with a particular name in the environment (a find function), and a function that binds data to a particular name in the environment ( a bind function), but I'm already stuck on the fenvEmpty part.

I presume the teacher wants you to raise an exception when attempting to look up an unbound value:
type name = string
type 'a fenv = name -> 'a
exception UnboundName of name
fun fenvEmpty name = raise UnboundName name
But I think it will help you more if you first try to use a version of fenv that returns NONE for unbound variables. I believe this because, as opposed to exceptions, there's more type structure to the program that will guide you while writing the implementation (see also below). So, first try to write this implementation where fenv is:
type 'a fenv = name -> 'a option
Now, for the later part of the question, you'll have to define a function for associating a name with a value to an existing environment. This would be that function's type:
val fenvAssoc : 'a fenv -> name -> 'a -> 'a fenv
Notice that the above returns a result of type 'a fenv. But remember what fenv actually is. It's "just" a function:
type 'a fenv = name -> 'a
So, this returned value, a function, needs to somehow "remember" the name and value that have been associated with it. How do functions normally "remember" things they've "seen" in the context where they've been defined?
To look up a name's value, you need a third function, which takes an existing environment and a name and returns the value for that name, if any:
val fenvLookup : 'a fenv -> name -> 'a
Again, remember what the type of 'a fenv is:
type 'a fenv = name -> 'a
I'm emphasizing this because the type of 'a fenv restricts you in the operations you can apply to it. You can basically either: a) create a function or b) apply one.

Related

How to use List.fold_left to populate keys of empty string map in ocaml?

I have an existing list, which I would like to move into a empty StringMap. I just want the items in this list to become the keys of said StringMap.
This is what I'm trying to do right now:
utop # List.fold_left StringMap.empty [1,2,3];;
Error: This expression has type 'a StringMap.t
but an expression was expected of type 'b -> 'c -> 'b
But clearly it's wrong as I'm getting the above error message
How should I go about this? Thanks in advance
List.fold_left takes three parameters: a function to be "folded", an initial value, and the list to be processed. You're only supplying two parameters. You need to supply a function that processes each element of the list and produces an intermediate result.
Here is an example that adds up all the elements of a list:
# List.fold_left (fun a b -> a + b) 0 [1;3;5;7];;
- : int = 16
You need a function like the one above except that it should add an element to the map.

Printing multiple lines of a dictionary

Suppose I define type
type person = { last_name: string; first_name: string; age: int};;
let person1 = {last_name="Doe"; first_name="John"; age=30};;
How can I print
Last name : Doe
First name : John
Age : 30
I thought using
match person1 with
| {last_name=ln; first_name=fn; age=a} -> print_string ...;;
but it seems not the way to go. If person1 and person were defined to be a dictionary with 1000 elements, then that solution doesn't hold.
Is there a better way to challenge that problem? Be aware that I have to use the functional paradigm. So I can't use while or for loop directly
It's hard to answer your question because you seem to have two different ideas of your type simultaneously. You can't have a type that's both a record and a dictionary. It's not possible.
Generally speaking, a dictionary is a collection of things. The convention for collections in OCaml is that they have a function named iter that traverses the collection.
Imagine you have an abstract collection defined by a module C. Conventionally you'll have a type 'a C.t for each collection, where 'a is the type of the elements of the collection. You'll also have (conventionally) a function C.iter of this type:
C.iter : ('a -> unit) -> 'a C.t -> unit
This means you can pass a function (like your printing function) to C.iter, and then also pass a collection. The iter function will traverse the collection and call your function for every element.
In your case the module C would define the dictionary you're imagining, and the type person C.t would be the type of a dictionary of the records you show above. The function C.iter would have the type (person -> unit) -> person C.t -> unit. In other words, it would take a function and apply it to all the persons in the dictionary, one after the other.
We can't really say more unless we know the details of the dictionary that you are planning to create.

Explanation why a list with different types is a valid Haskell expression needed

So in an exercise I am given a list like ["xyz", True, 42]. The question was if that is a valid expression in Haskell and what the type of that expression is.
A list can only hold homogenous types but the type of "xyz"is [Char], the type of True is Bool and the type of 42 is Num p => p. That is different types so I can't put them into a list.
That's what I thought. But the given answer to that exercise is "Yes, it is a valid expression. Show-instance!."
Why is it a valid expression although the types of the list elements are different and what is meant with show-instance? I'm thinking of something like superclasses from object oriented languages but I thought this is not how Haskell works.
If we are allowed to define some more context, we can make this a valid expression, for instance with:
import Data.String(IsString(fromString))
instance IsString Bool where
fromString [] = False
fromString _ = True
instance Num Bool where
(+) = (||)
(*) = (&&)
abs = id
signum = id
fromInteger 0 = False
fromInteger _ = True
negate = not
(here I used the truthiness of Python to convert from an Integer and String literal)
Then we can write it with the OverloadedStrings pragma:
{-# LANGUAGE OverloadedStrings #-}
the_list = ["xyz", True, 42]
This will then be equivalent to:
Prelude Data.String> ["xyz", True, 42]
[True,True,True]
But note that the list still contains only Bools, we only made Bool an instance of IsString and Num to enable us to convert string literals and number literals to Bools.
A list of heterogeneous types is not possible in Haskell, and since by default a Bool is not a Num, we thus can not parse that expression without adding some extra magic.
An additional note is that it is valid Haskell grammar: syntactically there is nothing wrong, it is only in the next stage of the compiler: type checking, etc. that it will raise errors, since the syntax is nonsensical.
My lecturer gave me a hint to check for Existential types in Haskell.
I produced a working example from the description from the link above:
{-# LANGUAGE ExistentialQuantification #-}
module Main where
data Showable = forall a . Show a => MkShowable a
pack:: Show a => a -> Showable
pack a= MkShowable a
instance Show Showable where
show (MkShowable a) = show a
hlist :: [Showable]
hlist = [pack "xyz", pack True, pack 42]
main :: IO ()
main = do
putStrLn "Heterogenous list 'camouflaged' as Showable:"
print hlist
This works and produces indeed the input from the exercise. The datatype extension for Existential Quantification in the first line is necessary.
My explanation (I might have gotten something wrong though):
I create a new type Showablewith one constructor MkShowable that takes any value a as long as it is in typeclass Show and thus makes a Showable out of it.
The method pack makes a Show a become a Showable by using the constructor MkShowable I described in 1.
Showable is made an instance of Show-typeclass and tells that if a Showable(MkShowable a) is to be shown, simply show a. So we can easily print our Showables.
Furthermore I created a (heterogenous) list hlist of type [Showable]and packed the values from my example into it, using pack. The list is printed in the main function.
This really reminds me of object-oriented programming.

Haskell List with tuples which can be extended - like a Dictionary

I am a beginner in Haskell and trying to learn it, so please excuse my obliviousness.
I am currently trying to implement a Telephone book, which is a List of tuples [(Name, Number)] (Both are Strings).
type TelephoneBook = [(String),(String)] (?)
However, I have no clue how I can extend this list by another tuple.
For example: [("Fred", "47/273")] and now I want to add another tuple.
I was trying to understand how the module dictionary works to see how I can extend this List and I stumbled upon "data" and "type".
An idea I had was to create a several types of this TelephonBook:
let a = TelephoneBook ("Fred","42/2321")
but that is just a simple idea... I am kinda lost on how to extend this list by another tuple, taking into account that once something is defined it can't be altered (or can it).
(Please don't give the solution to the Problem but simply an idea on how to start or what I should Research further)
The (:) operator prepends elements to lists. For example:
> ("John", "555-1212") : [("Fred", "42/2321")]
[("John","555-1212"),("Fred","42/2321")]
because you're asking to extend a list:
i have to disappoint you. That's not possible in Haskell. You can construct a new one. Out of one Element and another List.
the list type in Haskell is defined similar to:
-- 1 2 3 4
data [a] = a : [a] | []
-- 1: if you encounter the type [a]
-- 3: it is either
-- 2: an element `e` and a list `l` forming the new list `e:l`
-- 4: or an empty List `[]`
-- so the types of the constructors are:
-- (:) :: a -> [a] -> [a]
-- [] :: [a]
So having a new element and a list you can construct a new one, using (:)!
type Entry = (String, String)
type Book = [Entry]
addEntry :: Entry -> Book -> Book
addEntry e b = e : b -- this works, because book is just a list
-- without type aliases: (this is the same, but maybe slightly less nice to read)
addEntry' :: (String, String) -> [(String, String)] -> [(String, String)]
addEntry' e b = e : b
-- or even simpler:
addEntry'' = (:)
The type keyword in Haskell has to be understood as a type alias, so it's just another name for something, the representation in Haskell is the same.

OCaml: creating a record from a function

type node = {
lan: string;
lat: string;
};;
let rec read_nodes_from_list list = match list with
| Xml.Element("node", _, _)::list' -> {lan="A"; lat="B"}::read_nodes_from_list list'
;;
I tried this to create a node record but it doesn't work. And suppose I have another type that has same attributes of node, how can I tell ocaml which type object to create?
Thank you.
Obviously, your function didn't work because you forgot to match with empty list:
let rec read_nodes_from_list list = match list with
| Xml.Element("node", _, _)::list' -> {lan="A"; lat="B"}::read_nodes_from_list list'
| [] -> []
What you're actually trying to do is a map operation on list, so your function could be written more elegantly as follows:
let read_nodes_from_list list =
List.map (fun (Xml.Element("node", _, _)) -> {lan="A"; lat="B"}) list
However, the function may not work because pattern matching on Xml.Element is not exhaustive. You should be careful when handling remaining cases. For example, something like this would work:
let read_nodes_from_list list =
List.map (function | (Xml.Element("node", _, _)) -> {lan="A"; lat="B"}
| _ -> {lan=""; lat=""}) list
To answer your question about record types, it considers a bad practice to have two record types with the same field label. You still can put these record types in different submodules and distinguish them using module prefixes. But as I said, having two similar record types in the same module causes confusion to you and the OCaml compiler.