From e8290791da1df12f3d77e45851b7a16b704357db Mon Sep 17 00:00:00 2001 From: Robbie Gleichman Date: Wed, 4 Jan 2017 01:47:44 -0800 Subject: [PATCH] Improve whitespace in tutorial. Update tutorial svg. --- examples/tutorial.hs | 30 +++++++++++++++--------------- examples/tutorial.svg | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/tutorial.hs b/examples/tutorial.hs index 01adf56..2f98074 100644 --- a/examples/tutorial.hs +++ b/examples/tutorial.hs @@ -42,7 +42,7 @@ y = (*) ((+) 8 7) 2 {-That was probably not too surprising. How about this?-} f x = 3 * x -{- Let's try to figure it out. First look at the f. It's green and in an orange +{-Let's try to figure it out. First look at the f. It's green and in an orange box which indicates that it is bound to the result. Now look at the function application. It looks like 3 is being multiplied by something, but what? There is a line connecting the second argument of * to the dot in the green icon, @@ -191,9 +191,9 @@ Since constructors are functions, the match icon has a topology similar to the apply icon. Now that you are familiar with matches, here's a simple case expression. ---y = case maybeInt of --- Nothing -> 0 --- Just x -> x + 1 +y = case maybeInt of + Nothing -> 0 + Just x -> x + 1 -} y = case maybeInt of Nothing -> 0 @@ -215,8 +215,8 @@ the yellow result circle on the case icon, this would create many cycles in the graph, making the layout much messier. Guards and if expressions look like this: ---y | x == 0 = 1 ---- | otherwise = x + 1 +y | x == 0 = 1 + | otherwise = x + 1 -} y | x == 0 = 1 | otherwise = x + 1 @@ -231,17 +231,17 @@ topology, but they should look less similar in better icon versions. "If" expressions are rendered the same as a guard with only one Boolean. ---factorial x = --- if x == 0 --- then 1 --- else factorial (x - 1) * x +factorial x = + if x == 0 + then 1 + else factorial (x - 1) * x -} factorial x = if x == 0 then 1 else factorial (x - 1) * x -{- Bonus section: +{-Bonus section: The depth of an icon's application tree is called the nesting depth. For example, The icon representing "factorial (x - 1) * x" above has a nesting @@ -282,10 +282,10 @@ Glance essentially rewrites the second expression as: Notice that the nesting depth has been reduced from 3 to 2. ---factorial x = --- if x == 0 --- then 1 --- else x * factorial (x - 1) +factorial x = + if x == 0 + then 1 + else x * factorial (x - 1) -} factorial x = if x == 0 diff --git a/examples/tutorial.svg b/examples/tutorial.svg index e969497..d0d24a3 100644 --- a/examples/tutorial.svg +++ b/examples/tutorial.svg @@ -1,3 +1,3 @@ factorial*-110==-- else x * factorial (x - 1)-- then 1-- if x == 0--factorial x =Notice that the nesting level has been reduced from 3 to 2.x * factorial (x - 1)tofactorial (x - 1) * xTo enable the compose icon, we change the expressionuses a compose icon for the else expression.For example, if we slightly rewrite the factorial function above, Glancereduce the nesting depth.Glance figures out automatically when to use the compose icon in order toyfgxy = f (g x)For example:to a composition of functions.To reduce nesting depth, Glance has an icon that represents an argument applieddepth of 3.For example, The icon representing "factorial (x - 1) * x" above has a nestingThe depth of an icon's application tree is called the nesting depth. Bonus section:factorial1-*10==-- else factorial (x - 1) * x-- then 1-- if x == 0--factorial x ="If" expressions are rendered the same as a guard with only one Boolean.in better icon versions.topology (number of connections = 1 + 2 * n), but they should look less similarCurrently, the guard icon and the case icon look similar since they have similarto either the top or bottom of the mid-line.other side of the mid-line. The overall result that the guard is bound to connectscorresponding result expressions (e.g. x + 1) connect to the triangle on theThe Boolean expressions (e.g. x == 0) connect to the orange Ls, and theyotherwise1x+0x==1--- | otherwise = x + 1--y | x == 0 = 1Guards and if expressions look like this:were not allowed.as opposed to the case icon which would create many cycles if remote result circlesOn a side note, the lambda icon also creates a cycle, but it only creates one cyclegraph, making the layout much messier.the yellow result circle on the case icon, this would create many cycles in thethe result to a new yellow circle. If the result always had to be connected to(x + 1) is topologically connected to its pattern (Just x), Glance can connectuse any value from the pattern (Nothing). For the first match, since the resultconnects to the circle on the case icon since the right hand side (0) does notindicated with the yellow circle. The result for the second match (Nothing -> 0)and the result for each match (the textual part to the right of the arrow) isThe matches (the textual part left of the arrow) connect to the triangles,The case icon is the magenta icon with three yellow circles next to it.ymaybeIntNothing0Just1+-- Nothing -> 0-- Just x -> x + 1--y = case maybeInt ofNow that you are familiar with matches, here's a simple case expression.each other, even when displaying Glance drawings in black and white.apply icons should be made more dissimilar so that they can not be confused withit from the apply icon. In a future iteration of the Glance icons, the match andthe apply icon. The match icon is magenta to help distinguishSince constructors are functions, the match icon has the same shape asxJust3Just(Just x) = Just 3Continuing on, here is a simple pattern match.y218baz27++*44*2+-/y = (((2 + 4 * 4) - (7+ 2 + baz)*8)/21)Other tree layouts could make these large expressions much more readable.(just like long lines of code) become hard to read with the linear layout.The linear layout Glance currently uses is just the simplest. Large expressionsThere are many different ways that function application trees can be represented.y8*3+foo2bazy = foo (3 + bazOf2) (8* bazOf2) where bazOf2 = baz 2and Glance extracts the sub-expression into a separate (non-nested) icon.As soon as an expression is used more than once, the tree topology is lost,y2baz8*2baz3+fooy = foo (3 + (baz 2)) (8* (baz 2))to make its drawings more compact.sub-expression is only used once. Glance takes advantage of this tree topologyapplication has a tree topology, not a graph topology. The result of eachand no it does not look graphical. The core idea is that nested functiongraphical. Here graphical is referring to a graph topology,visual programming languages, you may be thinking that this does not look veryLets go back to the function apply icon. If you are used to other graphicalf1+f1 x y = (\z -> x + z) yafter layout so it would not make the drawing any larger.icons inside a function (including the function's lambda icon). This would occurfunction. To address this, I hope to have Glance draw a perimeter around allprobably take some time to figure out that x is only being used in an innerwhich function a parameter is used. In the code below for example, it wouldRegions however can still be useful to tell at what level, or in other words, inregions.In most other visual languages, the above code would require three nestedf1[,,]sumf1 = (\x1 -> (\x2 -> (\x3 -> sum [x1, x2, x3])))is not wasted by extra boxes.Theoretically, Glance's flat layout should allow more compact drawings since spacewould be restricted to a rectangle. In Glance, all icons are on the same level.In other visual programming languages, the icons inside the body of a functionSomething different about Glance is that Glance does not have any code regions.f240+-*2*max-- max (2 * y) q-f x y = let q = ((f (x + y - 40) x) * 2) in---------Drawing below:-----------------------------Scroll down for the drawing.Haskell functions only have one parameter).with "multiple parameters" are defined (which is of course syntactic sugar sinceyourself before scrolling down. One place to start is to figure out how functionsIf you have some drawing implements handy, you might want to try drawing this-- max (2 * y) q-f x y = let q = ((f (x + y - 40) x) * 2) inA more complex example:y73*y = (\x -> 3 * x) 7function application is bound to y.Here, the new function is applied to the argument 7, and the result of thef3*f = (\x -> 3 * x)which is connected to the blue square. The function itself is bound to the name f.and the return value 3 * x is the red circle in the function application icon,In this case, the formal parameter x is the dot inside the green lambda icon,that has been defined.of the -> in a lambda expression). The green circle represents the functionrepresents the value returned by function (i.e. what's on the right sizefunction. The dot inside the icon is the formal parameter. The blue squareNow for the answer. As you might have suspected. The green icon defines ay73*y has a value of 21.and a result that derives from the variable? Here's a hint.the argument. What construct in Haskell has three ingredients: a name, a variable,Nope, no green icon. The recursion of f is just indicated by a line from f tof3*Let's see what that looks like:f = 3 * f?Might it beLet's think of some possibilities.overall result f, the second argument to *, and the result of the multiplication.in the green icon. So the green icon represents a relationship between theThe result of the function application is also connected to the blue squareso the second line probably originates from the dot in the green icon.There is a line connecting the second argument of * to the dot in the green icon,function application. It looks like 3 is being multiplied by something, but what?box which indicates that it is bound to the result. Now look at the Let's try to figure it out. First look at the f. It's green and in an orangef3*That was probably not too surprising. How about this?y278+*y = (*) ((+) 8 7) 2Let's make things a bit more interesting with a nested function application.it means they have the same value. Line colors are randomized.etc.) in textual Haskell. Thus if two things are connected with a line in Glance,Lines in Glance are largely equivalent to names (variable names, function names,The meaning of Glance is entirely in how the icons are connected to each other.even if they are rotated, reflected, squashed or squished does not matter.icons (the non-text parts) are distinguishable from each other, how they are drawn,of the icons by themselves does not have much meaning. In fact, as long as theit will start looking much stranger from here on. Keep in mind that the designthe program text with some boxes, lines, triangles and circles. Don't worry,You might be thinking that so far it looks like Glance has just decoratedy53*y = 3 * 5Infix function application is displayed the same.y53*y = (*) 3 5For example, multiply 3 and 5 and bind the result to y.resultargumentfunctionMore explicitlyyxfThe function f is applied to the argument x, and the result is bound to y.Let's start with y = f x.programming language designs waiting to be discovered.visual programming languages, and that there is a huge universe of visualHow could it be extended? I feel that we are just at the very beginning ofWhy is Glance designed the way it is? What are other ways it could work?Glance drawings, but also to get you thinking about visual programming languages.Welcome to Glance! My goal for this tutorial is teach you how to read \ No newline at end of file + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">factorial*-110==factorial*-110== else x * factorial (x - 1) then 1 if x == 0factorial x =Notice that the nesting depth has been reduced from 3 to 2.(x *) . factorial . (x -) $ 1Glance essentially rewrites the second expression as:x * factorial (x - 1)tofactorial (x - 1) * xTo enable the compose icon, we change the expressionuses a compose icon for the else expression.For example, if we slightly rewrite the factorial function above, Glancereduce the nesting depth.Glance figures out automatically when to use the compose icon in order toyfghxyfghxy = (f . g . h) xwhich is the same asy = f (g (h x))With a composition of three functions:yfgxyfgxy = (f . g) xwhich is the same asy = f (g x)For example:to a composition of functions.To reduce nesting depth, Glance has an icon that represents an argument applieddepth of 3.For example, The icon representing "factorial (x - 1) * x" above has a nestingThe depth of an icon's application tree is called the nesting depth.Bonus section:factorial1-*10==factorial1-*10== else factorial (x - 1) * x then 1 if x == 0factorial x ="If" expressions are rendered the same as a guard with only one Boolean.topology, but they should look less similar in better icon versions.Currently, the guard icon and the case icon look similar since they have similarto the bottom of the mid-line.other side of the mid-line. The overall result that the guard is bound to connectscorresponding result expressions (e.g. x + 1) connect to the triangles on theThe Boolean expressions (e.g. x == 0) connect to the orange Ls, and they1x+otherwise10x==y1x+otherwise10x== | otherwise = x + 1y | x == 0 = 1Guards and if expressions look like this:graph, making the layout much messier.the yellow result circle on the case icon, this would create many cycles in theIf the result always had to be connected tothe result to a new yellow circle.(x + 1) is connected to its pattern (Just x), Glance can connectuse any value from the pattern (Nothing). For the second match, since the resultconnects to the circle on the case icon since the right hand side (0) does notThe result for the first match (Nothing -> 0)indicated with the yellow circle.and the result for each match (the textual part to the right of the arrow) isThe matches (the textual part left of the arrow) connect to the triangles,The case icon is the magenta icon with three yellow circles next to it.y1+Just0NothingmaybeInty1+Just0NothingmaybeInt Just x -> x + 1 Nothing -> 0y = case maybeInt ofNow that you are familiar with matches, here's a simple case expression.the apply icon.Since constructors are functions, the match icon has a topology similar tox3JustJustx3JustJust(Just x) = Just 3Continuing on, here is a simple pattern match.y218baz27++*44*2+-/y218baz27++*44*2+-/y = (((2 + 4 * 4) - (7+ 2 + baz)*8)/21)Other tree layouts could make these large expressions much more readable.(just like long lines of code) become hard to read with the linear layout.The linear layout Glance currently uses is just the simplest. Large expressionsThere are many different ways that function application trees can be represented.y8*3+foo2bazy8*3+foo2bazy = foo (3 + bazOf2) (8* bazOf2) where bazOf2 = baz 2and Glance extracts the sub-expression into a separate (non-nested) icon.As soon as an expression is used more than once, the tree topology is lost,y2baz8*2baz3+fooy2baz8*2baz3+fooy = foo (3 + (baz 2)) (8 * (baz 2))to make its drawings more compact.sub-expression is only used once. Glance takes advantage of this tree topologyapplication has a tree topology, not a graph topology. The result of eachand no it does not look graphical. The core idea is that nested functiondoes not look very graphical. Here graphical is referring to a graph topology,programming languages, you may be thinking that drawing belowLet's go back to the function apply icon. If you are used to other graphicalf1+f1+f1 x y = (\z -> x + z) yafter layout so it would not make the drawing any larger.to have Glance draw a perimeter around all icons inside a function. This would occurfigure out that x is only being used in an inner function. To address this, I hopeis used. In the code below for example, it would probably take some time toWithout regions however, it can be difficult to see in which function a parameterregions.In most other visual languages, the above code would require three nestedf1[,,]sumx3x2x1f1[,,]sumx3x2x1f1 = (\x1 -> (\x2 -> (\x3 -> sum [x1, x2, x3])))is not wasted by extra boxes.Theoretically, Glance's flat layout should allow more compact drawings since spacewould be restricted to a rectangle. In Glance, all icons are on the same level.In other visual programming languages, the icons inside the body of a functionSomething different about Glance is that Glance does not have any rigid code regions.f1+2*maxf1+2*maxf x y = max (2 * y) (1 + x)---------Drawing below:-----------------------------Scroll down for the drawing.Haskell functions only have one parameter).with "multiple parameters" are defined (which is of course syntactic sugar sinceyourself before scrolling down. One place to start is to figure out how functionsIf you have some drawing implements handy, you might want to try drawing thisf x y = max (2 * y) (1 + x)A more complex example:y73*y73*y = (\x -> 3 * x) 7function application is bound to y.Here, the new function is applied to the argument 7, and the result of thef3*f3*f = (\x -> 3 * x)which is connected to the blue square. The function itself is bound to the name f.and the return value 3 * x is the red circle in the function application icon,In this case, the formal parameter x is the dot inside the green lambda icon,that has been defined.of the -> in a lambda expression). The green circle represents the functionrepresents the value returned by function (i.e. what's on the right sizefunction. The dot inside the icon is the formal parameter. The blue squareNow for the answer. As you might have suspected. The green icon defines ay73*y73*y has a value of 21.and a result that derives from the variable? Here's a hint.What construct in Haskell has three ingredients: a name, a variable,overall result f, the second argument to *, and the result of the multiplication.in the green icon. So the green icon represents a relationship between theThe result of the function application is also connected to the blue squareso the second argument probably comes from the dot in the green icon.There is a line connecting the second argument of * to the dot in the green icon,function application. It looks like 3 is being multiplied by something, but what?box which indicates that it is bound to the result. Now look at theLet's try to figure it out. First look at the f. It's green and in an orangef3*f3*That was probably not too surprising. How about this?y278+*y278+*y = (*) ((+) 8 7) 2Let's make things a bit more interesting with a nested function application.it means they have the same value. Line colors are randomized.etc.) in textual Haskell. Thus if two things are connected with a line in Glance,Lines in Glance are largely equivalent to names (variable names, function names,The meaning of Glance is entirely in how the icons are connected to each other.even if they are rotated, reflected, squashed or squished does not matter.icons (the non-text parts) are distinguishable from each other, how they are drawn,of the icons does not have much meaning. In fact, as long as theit will start looking much stranger from here on. Keep in mind that the designthe program text with some boxes, lines, triangles and circles. Don't worry,You might be thinking that so far it looks like Glance has just decoratedy53*y53*y = 3 * 5Infix function application is displayed the same.y53*y53*y = (*) 3 5For example, multiply 3 and 5 and bind the result to y.resultargumentfunctionresultargumentfunctionMore explicitlyyxfyxfThe function f is applied to the argument x, and the result is bound to y.Let's start with y = f x.programming language designs waiting to be discovered.visual programming languages, and that there is a huge universe of visualHow could it be extended? I feel that we are just at the very beginning ofWhy is Glance designed the way it is? What are other ways it could work?Glance drawings, but also to get you thinking about visual programming languages.Welcome to Glance! My goal for this tutorial is teach you how to read \ No newline at end of file