Understanding modify function from THIH (Typing Haskell In Haskell) - haskell

I am reading typing haskell in haskell
Have a hard time understanding this line of coding on p 13
modify ce i c = ce{classes=\j→if I==j then Just c else classes ce j}
Where is j coming from? There is a brief covering on modify but no mentioning of j at all on p 13.
On p14, there is a call made to the return (modify ce i (is, [])) under the addClass. This is where I could not figure out. How can a call to modify ce i ( is, [])) be made if there is no j provided? Thanks for any help.

j is still part of the lambda expression
\j -> if i==j then Just c else classes ce j
that defines the value of the classes field. This function is a closure over the values i, c, and ce that modify itself receives as arguments.
It's a like a recursive function: the result of modify ce i c is an value where (for some values ce, i, c, and x)
classes (modify ce i c i) == Just c
and
classes (modify ce i c x) == classes ce x`.
Except instead of classes actually calling itself, modify creates an new value of type ClassEnv that wraps a "smaller" value of the same type. The classes function unwraps that environment one layer at a time until it either finds a matching value for the original argument, or it reaches the initialEnv value for which classes initalEnv _ == Nothing.

j is a lambda parameter. You can give a parameter any name you like. What does it represent? The type signature of modify tells us the first parameter is of type ClassEnv, so you can go read its definition (page 12) to see what type its classes field has.

To add to the other answers, what the author of that paper does is define a very simple map or dictionary using only functions. Normally you might write Map Id Class where Map is from the containers package, but you can also use the type Id -> Maybe Class which then basically is the lookup function for your map type. Then some simple functions can be implemented like this:
type Map k v = k -> Maybe v
singleton :: Eq k => k -> v -> Map k v
singleton k v = \k' -> if k == k' then Just v else Nothing
insert :: Eq k => k -> v -> Map k v -> Map k v
insert k v lookup = \k' -> if k' == k then Just v else lookup k'
union :: Map k v -> Map k v -> Map k v
union lookup1 lookup2 = \k -> case lookup1 k of
Nothing -> lookup2 k
v -> v
delete :: Eq k => k -> Map k v -> Map k v
delete k lookup = \k' -> if k == k' then Nothing else lookup k'
lookup :: Map k v -> k -> Maybe v
lookup = id
So, instead of defining the map as a collection of values, you define the map as the lookup function.
An advantage of this approach is that it is simple because it doesn't rely on external dependencies. But it is not so flexible: you cannot, for example, list all the keys and values in the map; and it is slow: lookups need to do a linear number of equality tests.

Related

How to use higher-order constructs in a particular case

I want to write a function that takes two Maybe Int parameters and returns the minimum of them if they are both Just number, and 'the other' if either of them is Nothing. I'm not satisfied with my first attempt:
maybeMin :: Maybe Int -> Maybe Int -> Maybe Int
maybeMin Nothing arr = arr
maybeMin ell Nothing = ell
maybeMin ell#(Just l) arr#(Just r) = if l < r then ell else arr
As an optimisation I don't want to create a new value in the third case; i.e., I don't want to write
maybeMin ell#(Just l) arr#(Just r) = Just $ if l < r then l else r
The above code seems clunky and it seems to me that I ought to be able to exploit the fact that Maybe is an instance of Functor, Applicative or Monad. However, my best attempt to go higher-order doesn't do the same thing:
maybeMin ell arr = ell >>= (\l -> arr >>= (\r -> if l < r then ell else arr))
because it will return Nothing if either operand be Nothing.
Is there an elegant way to do what I want?
You looked at Functor, Applicative, and Monad, but you may want to check out Alternative. As an example of its use, Just 3 <|> Nothing will yield Just 3 and not Nothing.
For your particular use, if you want a one-liner, you could try:
maybeMin l r = min l r <|> l <|> r
Just to break that down, we first calculate min l r, which uses the Ord instance of Maybe to give the minimum of l and r if both are Just values. If this works, then the computation stops there, but if either one isn't Just, then we check to see if l is a Just value. If it is, then that is the result, and if not, we end up returning r as the result.

Nested List Haskell Iteration

I need to implement a nested list operation in Haskell.
f :: [[String]] -> [[String]]
My input is a 2d array
[ [ ”A” , ”A” , ”A” ]
, [ ”B” , ”B” , ”A” ]
, [ ”A” , ”A” , ”B” ] ]
I arbitrarily generated that list.
A A A
B B A
A A B
So in my implementation I need to do the following.
If a position has A, and it has 2 or more than 2 "B" neighbors, it will turn to B.
If a position has B, and it has 2 or more than 2 "B" neighbors, it stays like as it is.
If a position has B, and it has less than 2 "B" neighbors, it will turn to A.
So after 1st step my table will look like this.
B B A
A B B
B B A
If I were going to use C or C++, my algorithm would like this:
Make a copy of my input.
Traverse both list in 2for loops, check if statements to make a change in the location and whenever I'm going to make a change, I will change the second list not the first, so that traversing the first list won't effect the other "A"'s and "B"'s.
Return second list.
The problem is, in Haskell, I cannot use iteration. How can I solve this problem?
As I stated in a comment, recursion is the looping primitive in Haskell. However, Haskell gives us a lot of power to build more user-friendly abstractions instead of using recursion directly. As #Lazersmoke mentioned, Comonad is a good abstraction when you're updating each individual value of a collection based on other values in the collection, such as the neighbors of the value.
There are quite a few examples of the Comonad class on the web, but it is sadly eclipsed by Monad. So here's my attempt to even the score a bit.
This is going to be a long post, so let me begin with the results. This is from GHCi:
λ display example
[[A,A,A],[B,B,A],[A,A,B]]
λ display (transition example)
[[B,B,A],[A,B,B],[B,B,A]]
Ok, now let's get down to business. First a few administrative things:
module Main where
import Control.Comonad -- from the comonad package
I'm going to try explaining each piece carefully, but it may take a while before the bigger picture becomes apparent. First, we're going to create an interesting data structure often called a zipper and implement an instance of Functor for it.
data U x = U [x] x [x] deriving Functor
instance Functor U where
fmap f (U as x bs) = U (fmap f as) (f x) (fmap f bs)
This data structure doesn't seem so special. It's how we use U that makes it cool. Because Haskell is lazy, we can use infinite lists with the U constructor. For example, i1 = U [-1,-2..] 0 [1,2..] represents all integers. That's not all, though. There's another piece of information: a center point at 0. We could have also represented all integers as i2' = U [0,-1..] 1 [2,3..]. These values are almost the same; they are just shifted by one. We can, in fact, create functions that will transform one into the other.
rightU (U a b (c:cs)) = U (b:a) c cs
leftU (U (a:as) b c) = U as a (b:c)
As you can see, we can slide a U to the left or the right just by rearranging elements. Let's make a Show instance for U and then verify that rightU and leftU work. We obviously can't print infinite lists, so we'll just take 3 elements from each side.
instance Show x => Show (U x) where
show (U as x bs) = (show . reverse . take 3) as ++ (show x) ++ (show . take 3) bs
λ i1
[-3,-2,-1]0[1,2,3]
λ leftU i2
[-3,-2,-1]0[1,2,3]
λ i2
[-2,-1,0]1[2,3,4]
λ rightU i1
[-2,-1,0]1[2,3,4]
Let's review our ultimate goal. We want to have a data structure where we can update each value based on all of its neighbors. Let's see how to do that with our U data structure. Suppose we want to replace each number with the sum of its neighbors. First, let's write a function that calculates the neighbors of the current position of a U:
sumOfNeighbors :: U Int -> Int
sumOfNeighbors (U (a:_) _ (b:_)) = a + b
And just to verify that it works:
λ sumOfNeighbors i1
0
λ sumOfNeighbors i2
2
Unfortunately, this only gives us a single result. We want to apply this function to every possible position. Well U has a Functor instance, so we can fmap a function over it. That would work great if our function had a type like Int -> Int, but it's actually U Int -> Int. But what if we could turn our U Int into a U (U Int)? Then fmap sumOfNeighbors would do exactly what we want!
Get ready for some inception-level data structuring. We're going to take our U Int and create a U (U Int) that will look like this:
-- not real Haskell. just for illustration
U [leftU u, (leftU . leftU) u, (leftU . leftU . leftU) u..] u [rightU u, (rightU . rightU) u, (rightU . rightU . rightU) u..]
This center of this new U (U a) is the original U a. When we slide left, we get original U a slid left, and likewise sliding right. In other words, the new U (U a) contains all the left and right slides of the original U a Here's how we do it:
duplicate :: U a -> U (U a)
duplicate u = U lefts u rights
where lefts = tail $ iterate leftU u
rights = tail $ iterate rightU u
We can use duplicate to write the function that we want:
extend :: (U a -> b) -> U a -> U b
extend f = fmap f . duplicate
Let's try it out.
λ extend sumOfNeighbors i1
[-6,-4,-2]0[2,4,6]
Looks like it works. These function names, duplicate and extend weren't chosen arbitrarily (by me, at least). These functions are part of the Comonad type class. We've been implementing it for our U data type.
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
The only thing missing is extract which is trivial for U:
extract (U _ x _) = x
It's probably not apparent how useful this class is yet. Let's move on and look at how to handle the 2-dimensional case. We can do 2-dimensions with a zipper of zippers. That is, U (U a) where moving left and right shifts the inner zippers, and moving up and down shifts the outer zipper.
newtype V a = V { getV :: U (U a) }
instance Functor V where
fmap f = V . (fmap . fmap) f . getV
-- shift the 'outer' zipper
up :: V a -> V a
up = V . leftU . getV
down :: V a -> V a
down = V . rightU . getV
-- shift the 'inner' zippers
left :: V a -> V a
left = V . fmap leftU .getV
right :: V a -> V a
right = V . fmap rightU . getV
Here's what Comonad looks like for V:
instance Comonad V where
extract = extract . extract . getV
duplicate = fmap V . V . dup . dup . getV
where dup u = U (lefts u) r (right u)
lefts u = tail $ iterate (fmap leftU) u
rights u = tail $ iterate (fmap rightU) u
The extract function is fairly straightforward; it just digs through two layers of zippers to grab the current value. On the other hand, duplicate is sort of a monster. Ignoring the newtype V, its type would be duplicate :: U (U a) -> U (U (U (U a))). The purpose of thedup helper function is to add a U layer. It gets invoked twice. Then we wrap that in V to get a V (U (U a)). Then fmap V wraps the inner U (U a) to make the result V (V a).
Oh by the way, if you're wondering where extend is, we don't actually have to write it. The definition given above is its default.
That was a lot of work, but now we'll be able to easily tackle the original problem! Check this out. I'm going to make a data structure that includes your A and B values, and also a value that we don't care about, C:
data Token = A | B | C deriving (Eq,Show)
And here's some stuff to make building and displaying a V easier.
-- a list of U's containing nothing but x's
filled x = repeat $ U (repeat x) x (repeat x)
type Triple a = (a,a,a)
-- create a U with the middle values a, b, and c, and all the other values the defaulted to d
toU :: a -> Triple a -> U a
toU d (a,b,c) = U (a : repeat d) b (c : repeat d)
-- create a V centered on the 9 given values and default all other values to d
toV :: a -> Triple (Triple a) -> V a
toV d (as, bs, cs) = V (U x y z)
where x = (toU d as) : filled d
y = toU d bs
z = (toU d cs) : filled d
display :: Show a => V a -> [[a]]
display v = fmap g [ [up . left, up, up . right]
, [left, id, right]
, [down . left, down , down . right] ]
where g = fmap (extract . ($ v))
Here's what the example looks like:
example = toV C ((A,A,A)
,(B,B,A)
,(A,A,B))
And the rule is implemented by:
-- move into each neighboring position and get the value in that position
neighbors :: V a -> [a]
neighbors v = fmap (extract . ($ v)) positions
where positions = [ up . left
, up
, up . right
, left
, right
, down . left
, down
, down . right ]
numberOfBs :: V Token -> Int
numberOfBs = length . filter (==B) . neighbors
rule :: V Token -> Token
rule v = case extract v of
C -> C -- C's remain C's forever
_ -> if numberOfBs v >= 2 then B else A
Finally, we can apply rule to every value using extend:
transition = extend rule
λ display (transition example)
[[B,B,A],[A,B,B],[B,B,A]]
This rule is kind of boring though. Everything quickly becomes B's.
λ take 10 $ fmap display (iterate transition example)
[[[A,A,A],[B,B,A],[A,A,B]],[[B,B,A],[A,B,B],[B,B,A]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,B,B],[B,B,B],[B,B,B]]]
Creating a different rule is easy.
rule2 :: V Token -> Token
rule2 v = case extract v of
C -> C
A -> if numberOfBs v >= 2 then B else A
B -> if numberOfBs v >= 4 then A else B
λ take 10 $ fmap display (iterate (extend rule2) example)
[[[A,A,A],[B,B,A],[A,A,B]],[[B,B,A],[B,B,B],[B,B,B]],[[B,A,B],[A,A,A],[B,A,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,A,B],[A,A,A],[B,A,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,A,B],[A,A,A],[B,A,B]],[[B,B,B],[B,B,B],[B,B,B]],[[B,A,B],[A,A,A],[B,A,B]],[[B,B,B],[B,B,B],[B,B,B]]]
Cool, right? One final thing I want to mention. Did you notice that we didn't write any special cases to handle the edges? Since the data structure is infinite, we just filled the stuff out of the range which we don't care about with the value C and ignored it when considering the neighbors.

Identifying input values for which a function does NOT generate a specific output

I built a data structure in form of a function that outputs certain strings in response to certain input strings like this:
type mydict = String -> String
emptydict :: mydict
emptydict _ = "not found"
Now I can add entries into this dictionary by doing the following:
addentry :: String -> String -> mydict -> mydict
addentry s1 s2 d s
| s1 == s = s2
| otherwise = d s
To look for s2's I can simply enter s1 and look in my dictionary
looky :: String -> mydict -> String
looky s1 d = d s1 --gives s2
My goal is now to create another function patternmatch in which I can check which s1's are associated with an s2 that starts with a certain pattern. Now the pattern matching itself isn't the problem, but I am not sure how can I keep track of the entries I entered, i.e. for which input is the output not "not found" ?
My idea was to try to keep track of all the s1's I entered in the addentry function and add them to a separate list. In patternmatch I would feed the list elements to looky, such that I can get back the associated s2's and check whether they match the pattern.
So my questions:
1) Is this list building approach good or is there a better way of identifying the inputs for which a function is defined as something other than "not found"?
2) If it is the right approach, how would I keep track of the s1's? I was thinking something like:
addentry s1 s2 d s
| last (save s1) == s = s2
| otherwise = d s1
And then save s1 being a function generating the list with all s1's. last (save s1) would then return the most recent s1. Would appreciate any help on implementing save s1 or other directions going from here. Thanks a lot.
Your design is hard-coded such that the only criteria for finding a key is by presenting the same exact key. What you need is a more flexible approach that lets you provide a criteria other than equality. I took the liberty of making your code more general and using more conventional names for the functions:
import Prelude hiding (lookup)
-- instead of k -> Maybe v, we represent the dictionary as
-- (k -> Bool) -> Maybe v where k -> Bool is the criteria
-- on which to match the key. by using Maybe v we can signal
-- that no qualifying key was found by returning Nothing
-- instead of "not found"
newtype Dict k v = Dict ((k -> Bool) -> Maybe v)
empty :: Dict k v
empty = Dict $ const Nothing
-- insert a new key/value pair
insert :: k -> v -> Dict k v -> Dict k v
insert k v d = Dict $ \f -> if f k then Just v else lookupBy f d
-- lookup using the given criteria
lookupBy :: (k -> Bool) -> Dict k v -> Maybe v
lookupBy f (Dict d) = d f
-- lookup using the default criteria (equality with some given key)
lookup :: Eq k => k -> Dict k v -> Maybe v
lookup k = lookupBy (k==)
-- your criteria
startsWith :: String -> String -> Bool
startsWith s = undefined -- TODO
lookupByPrefix :: String -> Dict String v -> Maybe v
lookupByPrefix = lookupBy . startsWith
I should mention that while this is a great exercise for functional programming practice and general brain-expansion, it's a terrible way to implement a map. A list of pairs is equivalent and easier to understand.
As a side note, we can easily define an instance of Functor for this type:
instance Functor (Dict k) where
fmap f d = Dict $ \g -> fmap f (lookupBy g d)

Maximum Clique finder in Haskell - parse error

I am trying to implement the Bron-Kerbosch algorithm for finding the number of maximum cliques (maximum Clique is a subset of a graph where every two verticies are connected and there is no larger clique containing it)
https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm
Unfortunately, I get an error : "parse error on input 'res' "
And I can't seem to solve it. I have tried to change the tap spaces with normal ones, but it doesn't seem to work. I also don't see any errors? Any ideas?
type Clique = [Vertex]
swarming::Clique->[Vertex]->[Vertex]->[Clique]
swarming R P X =
if null P && null X then [R]
else loop R X
where
loop::[Vertex]->[Vertex]->[Clique]
loop[] _ =[]
loop(v:R') X=
swarming (v:R)(P 'res' v)(X 'res' v)
loop P (v:X)
type Vertex = Int
class Graph g where
size ::g->Int
verticies ::g->[Vertex]
connected ::g->Vertex->Vertex->Bool
bron::Graph g=>g->[Clique]
bron g = swarming[] (verticies g) []
where
swarming R P X =
if null P && null X then [R]
else loop R X
where
loop::[Vertex]->[Vertex]->[Clique]
loop[] _ =[]
loop(v:R) X=
swarming (v:R)(P 'res' v)(X 'res' v)
loop P (v:X)
res::[Vertex]->Vertex->[Vertex]
res vs v = filter(connected g v) vs
As I can see there is a bit more wrong with your code than just the error you get:
first of all as the comment already says ' are reserved for single characters Char, the syntax you are looking for is `res`.
secondly I saw you are using tabs, newer versions of the ghc compiler will warn you about that, usually nowadays people use spaces (this is mostly a matter of taste and it is up to you)
I have slightly reordered your code and modified it in such a way it compiles. The undefined will raise a run-time error, but this state is better than a non-compiling one.
type Clique = [Vertex]
type Vertex = Int
class Graph g where
size :: g -> Int
vertices :: g -> [Vertex]
connected :: g -> Vertex -> Vertex -> Bool
I usually organize my code in a way that type/data/class declarations are on top of my file and the rest below that.
Syntax wise the next error you have is using upper case letters for variable names - this is not allowed in haskell. Types start with upper case variables with lower case.
bron is a tricky function and I honestly cannot quite figure out what you want to do there are two things that make this hard to figure out.
You have 'variables' r and r in both swarming and loop - it seems that they should be not the same, whereas p should be always the same.
Name shadowing is not a syntactic problem but a logical, it makes it easier if two different things have not the same name.
I see
loop ... = swarming
loop
this is invalid haskell syntax - what are you going to do with swarming it is not used in the following parts of the code, use let … in to stitch those two lines together
here is the rest of your code bron with a compiling but incomplete implementation
bron :: Graph g => g -> [Clique]
bron g = swarming [] (vertices g) []
where res :: [Vertex] -> Vertex -> [Vertex]
res vs v = filter (connected g v) vs
swarming :: Clique -> [Vertex] -> [Vertex] -> [Clique]
swarming r [] [] = [r]
swarming r p x = loop r x
where loop :: [Vertex] -> [Vertex] -> [Clique]
loop [] _ = []
loop (v:r) x = undefined
-- let sw = swarming (v:x) (p `res` v) (x `res` v)
-- in loop ??

What is being passed in?

In the code:
oneChar :: Char -> Doc
oneChar c = case lookup c simpleEscapes of
Just r -> text r
Nothing | mustEscape c -> hexEscape c
| otherwise -> char c
where mustEscape c = c < ' ' || c == '\x7f' || c > '\xff'
simpleEscapes :: [(Char, String)]
simpleEscapes = zipWith ch "\b\n\f\r\t\\\"/" "bnfrt\\\"/"
where ch a b = (a, ['\\',b])
r isn't being passed to oneChar. Where does r come from?
lookup c simpleEscapes returns a Maybe String value, which can be either Nothing or Just <a string>. r is the string contained in the Just, as defined by the line:
Just r -> text r
The case keyword introduces a pattern match, which has the form case EXPR of (PATTERN -> EXPR)+. So Just r is a pattern, that matches the result of lookup c simpleEscapes of. In a pattern, variables can be bound. Basically this means, if lookup c simpleEscapes of returns a Just then r will be bound to the value inside that Just and the result of the expression will be text r.
If you're asking where the identifier is introduced, it's bound by the pattern match in the case statement, the same way the identifier c is bound by the pattern match in the function definition.
Any pattern match can introduce a new identifier for the associated expression:
(\(Just x) -> x) foo
let (Just x) = foo in x
f (Just x) = x
case foo of
Just x -> x
...all of those introduce a new identifier named x. In fact, they're all pretty much equivalent, because the compiler converts all of them into case blocks under the hood.
You're using a case statement on the value returned by lookup c simpleEscapes, which is of type Maybe. Maybe has two data constructors: Just and Nothing. The Just data constructor is parameterized by one value, the Nothing data constructor has no parameters.
So in this case, r is the formal parameter to the Just data constructor: its the actual value in the returned value from lookup.

Resources