It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am learning Haskell and I want to understand types. Assume that I have an object of type Store:
import Data.Map (Map)
import qualified Data.Map as Map
type Variable = String
data Value = IntVal Int
| BoolVal Bool
type Store = Map Variable Value
How can use this object, say s to get value of variable?
And how to save value of a variable in Store?
In a type declaration, the token on the left of the = is the type's name. Values to the right of the = define constructors - functions that create an instance of that type.
Consider the definition of Maybe, a simple type that represents the possibility of a failure (represented as null or nil in many languages):
data Maybe a = Just a | Nothing
This is a type with two constructors: Just and Nothing:
The Just constructor represents success. It requires an argument of any type, representing the value to wrap
The Nothing constructor takes no arguments. It represents failure.
You can see here that because Maybe has two constructors, there are two ways of constructing Maybe values. Such types are called union types. You extract values from union types using pattern matching. There are several language constructs that allow pattern matching (let and where-bindings, case statements, and function variable bindings). Below, we destructure a Just value in the arguments to a function.
fromJust :: Maybe a -> a
fromJust (Just x) = x
Assume this is loaded into GHCI. Here, we create an instance of Maybe, using the Just constructor, then retrieve that value again:
> let x = Just 20
> fromJust x
20
Here's how pattern matching looks for your types. We create an instance of the Store type using the Map constructor you've defined:
> let m = Map "someVar" $ IntVal 0
Below we define a function that will extract the Variable value from a Map.
getVariable :: Store -> Variable
getVariable (Map v _) = v
Applying the function:
> getVariable m
"someVar"
Hopefully the resources you're learning from will cover this stuff soon. If not, I recommend a dose of Real World Haskell.
Here's some example usage:
s :: Store
s = fromList [("key1", IntVal 4), ("key2", BoolVal False)]
lookup "key1" s -- Just (IntVal 4)
lookup "key2" s -- Just (BoolVal False)
lookup "key3" s -- Nothing
s' :: Store
s' = insert "key3" (BoolVal True) s
lookup "key3" s' -- Just (BoolVal True)
Related
For a uni assignment, a function "lookup" has been defined as:
lookup :: Env e -> String -> Maybe e
The "Env" keyword has been defined as:
import qualified Data.Map as M
newtype Env e = Env (M.Map String e) deriving (Functor, Foldable, Traversable, Show, Eq, Monoid, Semigroup)
I understand that the double colon "::" means "has type of". So the lookup function takes two arguments and returns something. I know the second argument is a string, however, I'm struggling to understand the first argument and the output. What is the "Env" type and what does the "e" after it represent. It feels like e is an argument to "Env" but if that is the case, the output wouldn't make sense.
Any help would be appreciated.
It feels like e is an argument to "Env" but if that is the case, the output wouldn't make sense.
That's the direction the syntax is trying to "feel like", because that's what it means. Env is a parameterised type, and e is being passed as an argument to that parameter.
I'm not 100% sure why you think the output wouldn't make sense, under that interpretation? Maybe is also a parameterised type, and the variable e is also being passed to Maybe; this is no different than using a variable twice in any piece of code. You can think of it as something like this pseudo-code:
lookupType(e) {
argument1_type = Env(e)
argument2_type = String
result_type = Maybe(e)
}
Is your confusion that you are thinking of e in the type signature of lookup not as being passed to Env, but as being defined to receive the argument of Env? That happens in the place where Env is defined, not where it is used in the type of lookup. Again, this is just like what happens at the value level with function arguments; e.g. when you're writing code to define a function like plus:
plus x y = x + y
Then the x and y variables are created to stand for whatever plus is applied to elsewhere. But in another piece of code where you're using plus, something like incr x = plus x 1 here the variable is just being passed to plus as an argument, it is not defined as the parameter of plus (it was in fact defined as the parameter of incr).
Perhaps the thing that you need more explicitly called out is this. lookup :: Env e -> String -> Maybe e is saying:
For any type e that you like, lookup takes an Env e and a String and returns a Maybe e
Thus you could pass lookup an Env Integer and a String, and it will give you back a Maybe Integer. Or you could pass it an Env (Maybe [(String, Float)]) and a String, and it will give you back a Maybe (Maybe [(String, Float)]). This should hopefully be intuitive, because it's just looking up keys in an environment; whatever type of data is stored in the environment you pass to lookup is the type that lookup will maybe-return.
The e is there because in fact lookup is parametrically polymorphic; it's almost like lookup takes a type argument called e, which it can then pass to other things in its type signature.1 That's why I wrote my pseudo-code the way I did, above.
But this is just how variables in type signatures work, in base Haskell2. You simply write variables in your type signature without defining them anyway, and they mean your definition can be used with ANY type at the position you write the variable. The only reason the variables have names like e (rather than being some sort of wildcard symbol like ?) is because you often need to say that you can work with any type, but it has to be the same type in several different places. lookup is like that; it can take any type of Env and return any sort of Maybe, but they have to be consistent. Giving the variable the name e merely allows you to link them to say that they're the same variable.
1 This is in fact exactly how types like this work at a lower level. Haskell normally keeps this kind of type argument invisible though; you just write a type signature containing variables, without defining them, and every time you use the accompanying binding the compiler figures out how the variables should be instantiated.
2 In more advanced Haskell, when you turn on a bunch of extensions, you can actually control exactly where type variables are introduced, rather than it always happening automatically at the beginning of every type signature you use with variables. You don't need to know that yet, and I'm not going to talk about it further.
I'll try to give concrete examples, providing and motivating intuition. With thtat intuition, I think the question has a very natural answer:
e is a type variable, and the lookup function wants to work on all possible environments, regardless of which concrete type e is". The unbound e is a natural way to syntactically express that
Step 1, the Env type
The Env type is a wrapper for Map type in the Data.Map module in the containers package. It is a collection of key-value pairs, and you can insert new key-value pairs and look them up. If the key you are looking up is missing, you must return an error, a null value, a default or something else. Just like hashmaps or dictionaries in other programming languages.
The documentation (linked above) writes
data Map = Map k a
A Map from keys k to values a.
and we will try that out and wee what k and a can be.
I use ghci to get interactive feedback.
Prelude> import Data.Map as M
Prelude M> map1 = M.fromList [("Sweden","SEK"),("Chile","CLP")]
Prelude M> :type map1
map1 :: Map [Char] [Char]
Prelude M> map2 = M.fromList [(1::Integer,"Un"),(2,"deux")]
Prelude M> :type map2
map2 :: Map Integer [Char]
Prelude M> map3 = fromList [("Ludvig",10000::Double),("Mikael",25000)]
Prelude M> :type map3
map3 :: Map [Char] Double
You can see that we create various mappings based on lists of key-value pairs.The type signature in the documentation Map k a correspond to different k and a in the ghci session above. For map2, k correspongs to Integer and a to [Char].
You can also see how I declared manual types at some places, using the double colon syntax.
To reduce the flexibility, we can create a new "wrapping" type that for M.Map. With this wrapper, we make sure that the keys are always Strings.
Prelude M> newtype Env e = Env (M.Map String e) deriving (Show)
this definition says that the type Env e is, for every e an alias for M.Map String e. The newtype declaration further says that we must always be explicit and wrap the mappings in a Env value constructor. Let see if we can do that.
Prelude M> Env map1
Env (fromList [("Chile","CLP"),("Sweden","SEK")])
Prelude M> Env map2
<interactive>:34:6: error:
• Couldn't match type ‘Integer’ with ‘[Char]’
Expected type: Map String [Char]
Actual type: Map Integer [Char]
• In the first argument of ‘Env’, namely ‘(map2)’
In the expression: Env (map2)
In an equation for ‘it’: it = Env (map2)
Prelude M> Env map3
Env (fromList [("Ludvig",10000.0),("Mikael",25000.0)])
In the session above, we see that both map1 and map3 can be wrapped in an Env, since they have an appropriate type (they have k==String), but map2 cannot (having k==Integer).
The logical step from Map to Env is a little tricky, since also renames some variables. What was called a when talking about maps, is called e in the Env case. But variable names are always arbitrary, so that is ok.
Step 2, the lookup
We have established that Env e is a wrapping type that contains a lookup table from strings to values of some type e. How do you lookup things? Let us start with the non-wrapped case, and then the wrapped case. In Data.Map there is a function called lookup. Lets try it!
Prelude M> M.lookup "Ludvig" map3
Just 10000.0
Prelude M> M.lookup "Elias" map3
Nothing
Okay, to look up a value, we supply a key, and get just the corresponding value. If the key is missing, we get nothing. What is the type of the return value?
Prelude M> :type M.lookup "Ludvig" map3
M.lookup "Ludvig" map3 :: Maybe Double
when making a lookup in a Data [Char] Double, we need a key of type [Char] and return a vlue of type Maybe Double. Okay. That sounds reasonable. What about some other example?
Prelude M> :type M.lookup 1 map2
M.lookup 1 map2 :: Maybe [Char]
when making a lookup in a Data Integer [Char], we need a key of type Integer and return a value of type Maybe [Char]. So in general, to lookup we need a key of type k and a map of type M.Map k a and return a Maybe a.
Generally, we think M.lookup :: k -> M.Map k a -> Maybe a. Lets see if ghci agrees.
Prelude M> :t M.lookup
M.lookup :: Ord k => k -> Map k a -> Maybe a
It does! It also requires that the k type must be some type with a defined order on it, such as strings or numbers. That is the meaning of the Ord k => thing in the beginning. Why? Well, it has to do with how M.Map type is defined... do not care too much about it right now.
We can specialize the type signature if we set k to be String. In that special case, it would look like
M.lookup :: String -> Map String a -> Maybe a
hmm. this inspires us to flip the order of argument 1 and 2 to lookup, and replace the variable a with e. It is just a variable, and names on variables are arbitrary anyways... Lets call this new function myLookup
myLookup :: Map String e -> String -> Maybe e
and since Env a is essentially the same as Map String e, if we just unwrap the Env type, we may define
myLookup :: Env a -> String -> Maybe e
how does one implement such a function? One way is to just unwrap the type by pattern matching, and let the library to the heavy lifting.
myLookup (Env map) key = M.lookup key map
Conclusion
I have tried to build up concrete examples using functions and types from the standard library of Haskell. I hope I have illustrated the idea of a polymorhic type (that M.Map k a is a type when supplied with a k and a v) and that Env is a wrapper, specializing to the case when k is a String.
I hope that this concrete example motivates why the type signatures looks like they do and why type variables are useful.
I have not tried to give you the formal treatment with terminology. I have not explained the Maybe type, nor typeclasses and derived typeclasses. I hope you can read up on that elsewhere.
I hope it helps.
I have defined two types as shown below with Vname representing a variable name as a string and Val representing an integer value:
type Vname = String
type Val = Int
type State = ...
with the type State still to be defined (I am also not sure if I have done Vname and Val correctly either). State has to be a mapping between Vname and Val and I assume it would be along the lines of:
type State = Vname->Val
but I am really not sure. Any clarification on this would be helpful.
it is for an implementation of a low-level machine with commands to operate a stack, with Vname being the variable name of the number you are putting onto the stack and Val being the value. The types are there for custom ghci input names.
Thank you.
To be precise, you've defined two type aliases, not two types.
State could be a function:
type State = Vname -> Maybe Val
foo :: State
foo "x" = Just 3
foo "y" = Just 5
-- etc
foo _ = Nothing
or it could be a list of name/value pairs.
type State' = [(Vname, Val)]
foo' :: State'
foo' = [("x", 3), ("y", 5)]
Note that foo and \x -> lookup x foo' (or flip lookup foo') are basically the same function.
Which you choose depends mostly on how you plan to use a value of type State. Sometimes the function will be more convenient, other times the list of pairs. I might lean toward the list, as it's easier to create a functional form (using lookup, as shown above) from a list than it is to create a list from a function (as that requires a list of values to apply the function to).
Coming from OOP this seems like alien code to me.
I don't understand why type of runIdentity is a function :
runIdentity :: Identity a -> a ? I specified to be runIdentity :: a
newtype Identity a = Identity {runIdentity :: a} deriving Show
instance Monad Identity where
return = Identity
Identity x >>= k = k x
instance Functor Identity where
fmap f (Identity x) = Identity (f x)
instance Applicative Identity where
pure = Identity
Identity f <*> Identity v = Identity (f v)
wrapNsucc :: Integer -> Identity Integer
wrapNsucc = Identity . succ
Calling runIdentity :
runIdentity $ wrapNsucc 5 -- gives 6 as output
You're right that runIdentity is but a simple field of type a. But the type of runIdentity is Identity a -> a, since runIdentity is a function to extract that field out of a Identity a. You can't get the runIdentity out of a value without supplying which value to get it from, after all.
Edit:
To expand a little on that OOP-analogy in the comments, think of a class
class Identity<T> {
public T runIdentity;
}
This is the Identity monad, loosely translated to OOP code. The template argument T basically is your a; as such, runIdentity is of type T. To get that T from your object, you'd probably do something like
Identity<int> foo = new Identity<int>();
int x = foo.runIdentity;
You see runIdentity as something of type T, but it's not really. You can't just do
int x = runIdentity; // Nope!
because - where to get the runIdentity from? Instead, think of this like doing
Identity<int> foo = new Identity<int>();
int x = runIdentity(foo);
This shows what actually happens when you're calling a member; you have a function (your runIdentity) and supply it an object to use - IIRC this is what Python does with def func(self). So instead of being plainly of type T, runIdentity is actually taking an Identity<T> as argument to return a T.
Thus, it's of type Identity a -> a.
Another way to see this is that record syntax in Haskell is basically just syntactic sugar over algebraic datatypes, i.e. records don't truly exist in Haskell, only algebraic datatypes do, with perhaps some additional syntactic niceties. Hence there isn't a notion of members the same way that classes have in a lot of OO languages.
data MyRecord = MyRecord { myInt :: Int, myString :: String }
really is just
data MyRecord Int String
with the additional functions
myInt :: MyRecord -> Int
myInt (MyRecord x _) = x
myString :: MyRecord -> String
myString (MyRecord _ y) = y
automatically defined.
The only things that you could not do by yourself with normal algebraic datatypes that record syntax gives you are a nice way of making a copy of MyRecord that only has a subset of fields changed and a nice way of naming certain patterns.
copyWithNewInt :: Int -> MyRecord -> MyRecord
copyWithNewInt x r = r { myInt = x }
-- Same thing as myInt, just written differently
extractInt :: MyRecord -> Int
extractInt (MyRecord { myInt = x }) = x
Because this is just syntactic sugar over ordinary algebraic datatypes, you could always fall back to doing things the usual way.
-- This is a more verbose but also valid way of doing things
copyWithNewInt :: Int -> MyRecord -> MyRecord
copyWithNewInt x (MyRecord _ oldString) = MyRecord x oldString
Incidentally this is why some otherwise ridiculous-seeming constraints exist (the most prominent is that you can't have another type defined with record syntax with myInt again, otherwise you're creating two functions in the same scope with the same name, which Haskell does not allow).
Therefore
newtype Identity a = Identity {runIdentity :: a} deriving Show
is equivalent (minus convenient update syntax which doesn't really matter when you have only one field) to
newtype Identity a = Identity a deriving Show
runIdentity :: Identity a -> a
runIdentity (Identity x) = x
Using record syntax just compresses all that into a single line (and perhaps gives more insight into why runIdentity is named that, i.e. as a verb, rather than as a noun).
newtype Identity a = Identity {runIdentity :: a} deriving Show
Using the record syntax here, you're really creating two things called runIdentity.
One is the field of the constructor Identity. You can use that with record pattern syntax, as in case i of Identity { x = runIdentity } -> x, where matching a value i :: Identity a to extract the field's contents into a local variable x. You can also use record construction or update syntax, as in Identity { runIdentity = "foo" } or i { runIdentity = "bar" }.
In all of those cases runIdentity isn't really a standalone thing in its own right. You're using it only as part of a larger syntactic construct, to say which field of Identity you're accessing. The "slot" of Identify a referred to with the help of the field runIdentity does indeed store things of type a. But this runIdentity field is not a value of type a. It's not even a value at all really, since it needs to have these extra properties (that values do not have) about referring to a particular "slot" in a data type. Values are standalone things, that exist and make sense on their own. Fields are not; field contents are, which is why we use types to classify fields, but fields themselves are not values.1 Values can be placed in data structures, returned from functions, etc. There's no way to define a value that you can place in a data structure, get back out, and then use with record pattern, construction, or update syntax.
The other thing named runIdentity defined with the record match syntax is an ordinary function. Functions are values; you can pass them to other functions, put them in data structures, etc. The intent is to give you a helper for getting the value of a field in a value of type Identity a. But because you have to specify which Identity a value you want to get the value of the runIdentity field from, you have to pass an Identity a into the function. So the runIdentity function is a value of type Identity a -> a, as distinct from the runIdentity field which is a non-value described by type a.
A simple way to see this distinction is to add a definition like myRunIdentity = runIdentity to your file. That definition declares that myRunIdentity is equal to runIdentity, but you can only define values like that. And sure enough myRunIdentity will be a function of type Identity a -> a, that you can apply to things of type Identity a to get an a value. But it won't be usable with record syntax as the field. The field runIdentity didn't "come along with" the value runIdentity in that definition.
This question might have been prompted by type :t runIdentity into ghci, asking it to show you the type. It would have answered runIdentity :: Identity a -> a. The reason is because the :t syntax works on values2. You can type any expression at all there, and it will give you the type of the value that would result. So :t runIdentity is seeing the runIdentity value (the function), not the runIdentity field.
As a final note, I've been banging on about how the field runIdentity :: a and the function runIdentity :: Identity -> a are two separate things. I did so because I thought cleanly separating the two would help people confused by why there can be two different answers to "what is the type of runIdentity". But it's also a perfectly valid interpretation to say that runIdentity is a single thing, and it's simply the case that when you use a field as a first-class value it behaves as a function. And that is how people often talk about fields. So please don't be confused if other sources insist that there is only one thing; these are simply two different ways of looking at the same language concepts.
1 A perspective on lenses, if you've heard of them, is that they are ordinary values that can be used to give us all of the semantics we need from "fields", without any special-purpose syntax. So a hypothetical language could theoretically not provide any syntax for field access at all, just giving us lenses when we declare a new data type, and we'd be able to make do.
But Haskell record syntax fields aren't lenses; used as values they're only "getter" functions, which is why there's dedicated pattern match, construction, and update syntax for using the fields in ways beyond what is possible with ordinary values.
2 Well, more properly it works on expressions, since it's type-checking the code, not running the code and then looking at the value to see what type it is (that wouldn't work anyway, since runtime Haskell values don't have any type information in the GHC system). But you can blur the lines and call values and expressions the same kind of thing; fields are quite different.
{-# LANGUAGE NamedFieldPuns #-}
data Factory = Factory { fId :: Int}
data Link = Link Int Int Double
hasLinkTo :: Factory -> Link -> Bool
hasLinkTo Factory{fId} (Link fId _ _) = True
Got error
• Conflicting definitions for ‘fId’ Bound at: <source.hs> In an equation for ‘hasLinkTo’
I know using variables could fix it,
hasLinkTo Factory{fId=a} (Link b _ _) = a == b
I want to ask for
reason of compilation fail, to better understand how pattern matching work.
is there any idiomatic way to write the function?
for example: if I want to extract what link to a node i, I want to write something like this
connected :: Int -> Link -> (Int, Double)
connected i (Link i j d) = (j,d)
connected i (Link j i d) = (j,d)
Is there any way to check for (==) using only pattern matching on non-numeric literals?
connected 0 (Link 0 j d) = (j,d) is working fine. but the above example won't.
Record punning with Factory{fId} is only syntactic sugar which GHC expands to Factory{fId=fId}. This declared a variable named fId with the value of the field named fId from the Factory record.
Furthermore, pattern matching only declares variables. It does not allow you to compare them by repeating the same name. Consider an attempt to compare equality:
eq a a = True
eq _ _ = False
This is a simple example that tried to do the same thing you are. It will not compile, though.
In the same way, the compiler complains because you declare two variables when you do (Link fId _ _). This is not allowed. Instead you need to use another name and explicitly compare the two:
hasLinkTo Factory{fId} (Link fInd' _ _) = fId == fId'
Haskell only allows linear patterns, where each variable can appear at most once. I believe that this was a deliberate design choice. Theoretically speaking
case e1 of C x x y -> e2 ; ...
could be automatically translated to
case e1 of C x1 x2 y | x1==x2 -> e2 ; ...
This would mean that non linear patterns require an additional Eq constraint for the types of non-linear variables. Further, it could be argued that it is possible for a programmer to accidentally reuse a variable by mistake, which would be silently ignored and lead to the unintended semantics if we allowed non-linear patterns.
Probably, the Haskell designers felt that adding | x1==x2 to a pattern was not too cumbersome and makes the intent more explicit.
For numeric literals, however, they kept this translation. A pattern
case e1 of K 0 y z -> e2 ; ...
does translate to
case e1 of K x y z | x==0 -> e2 ; ...
and does require Eq. Since 0 is not a variable, we no longer have the issues of non-linear patterns.
Anyway, the idiomatic way is to add guards like | x1==x2 to non-liner patterns.
You can't use only pattern matching for this at the moment.
Given the following types:
import Data.Set as Set
-- http://json.org/
type Key = String
data Json = JObject Key (Set JValue)
| JArray JArr
deriving Show
data JObj = JObj Key JValue
deriving Show
data JArr = Arr [JValue] deriving Show
data Null = Null deriving Show
data JValue = Num Double
| S String
| B Bool
| J JObj
| Array JArr
| N Null
deriving Show
I created a JObject Key (Set Value) with a single element:
ghci> JObject "foo" (Set.singleton (B True))
JObject "foo" (fromList [B True])
But, when I tried to create a 2-element Set, I got a compile-time error:
ghci> JObject "foo" (Set.insert (Num 5.5) $ Set.singleton (B True))
<interactive>:159:16:
No instance for (Ord JValue) arising from a use of ‘insert’
In the expression: insert (Num 5.5)
In the second argument of ‘JObject’, namely
‘(insert (Num 5.5) $ singleton (B True))’
In the expression:
JObject "foo" (insert (Num 5.5) $ singleton (B True))
So I asked, "Why is it necessary for JValue to implement the Ord typeclass?"
The docs on Data.Set answer that question.
The implementation of Set is based on size balanced binary trees (or trees of bounded balance)
But, is there a Set-like, i.e. non-ordered, data structure that does not require Ord's implementation that I can use?
You will pretty much always need at least Eq to implement a set (or at least the ability to write an Eq instance, whether or not one exists). Having only Eq will give you a horrifyingly inefficient one. You can improve this with Ord or with Hashable.
One thing you might want to do here is use a trie, which will let you take advantage of the nested structure instead of constantly fighting it.
You can start by looking at generic-trie. This does not appear to offer anything for your Array pieces, so you may have to add some things.
Why Eq is not good enough
The simplest way to implement a set is using a list:
type Set a = [a]
member a [] = False
member (x:xs) | a == x = True
| otherwise = member a xs
insert a xs | member a xs = xs
| otherwise = a:xs
This is no good (unless there are very few elements), because you may have to traverse the entire list to see if something is a member.
To improve matters, we need to use some sort of tree:
data Set a = Node a (Set a) (Set a) | Tip
There are a lot of different kinds of trees we can make, but in order to use them, we must be able, at each node, to decide which of the branches to take. If we only have Eq, there is no way to choose the right one. If we have Ord (or Hashable), that gives us a way to choose.
The trie approach structures the tree based on the structure of the data. When your type is deeply nested (a list of arrays of records of lists...), either hashing or comparison can be very expensive, so the trie will probably be better.
Side note on Ord
Although I don't think you should use the Ord approach here, it very often is the right one. In some cases, your particular type may not have a natural ordering, but there is some efficient way to order its elements. In this case you can play a trick with newtype:
newtype WrappedThing = Wrap Thing
instance Ord WrappedThing where
....
newtype ThingSet = ThingSet (Set WrappedThing)
insertThing thing (ThingSet s) = ThingSet (insert (Wrap thing) s)
memberThing thing (ThingSet s) = member (WrapThing) s
...
Yet another approach, in some cases, is to define a "base type" that is an Ord instance, but only export a newtype wrapper around it; you can use the base type for all your internal functions, but the exported type is completely abstract (and not an Ord instance).