What is wrong with my haskell general tree? - haskell

Here is my code and there are so many things wrong about it that i can't see.
What is the problem? or what "are" the problems?? I get these errors for several lines:
Data constructor not in scope. NBaum
Couldn't match expected type [NBaum [Char]]' with actual type `NBaum [Char]'
In the second argument of NKnoten', namely `(NBlatt "Io")'
In the sixth argument of `NBaum', namely
data NBaum a = NBlatt a | NKnoten a [NBaum a]
deriving(Eq,Show)
tree :: NBaum String
tree =
NBaum "Sonne"
(NKnoten "Erde"
(NBlatt "MOND" )
)
(NBlatt "Merkur" )
(NBlatt "Venus" )
(NKnoten "MARS"
(NBlatt "PHOBOS" )
(NBlatt "DEIMOS" )
)
(NKnoten "JUPITER"
(NBlatt "Io" )
(NBlatt "EUROPA" )
(NBlatt "GANYMED" )
(NBlatt "KALLISTO" )
)

The problem is that if you describe a list [], you do this between square brackets separated with commas, like [1,4,2,5]. Not between round brackets: that is a tuple.
tree :: NBaum String
tree = NKnoten "Sonne" [
NKnoten "Erde" [NBlatt "MOND"],
NBlatt "Merkur",
NBlatt "Venus",
NKnoten "MARS" [
NBlatt "PHOBOS",
NBlatt "DEIMOS"
],
NKnoten "JUPITER" [
NBlatt "Io",
NBlatt "EUROPA",
NBlatt "GANYMED",
NBlatt "KALLISTO"
]
]
Furthermore - as is highlighted in the code fragment - you (probably accidentally) - wrote the type name (NBaum) instead of constructor name (NKnoten) at the first object (the "Sonne").

Related

Pretty-printing JavaScript objects

I've chosen to center this question around JSON objects and wl-pprint-annotated (here is the paper behind that library) because they make it easy to have an MVCE, but my problem is not actually around pretty-printing just JSON objects and I am flexible for which pretty-printing library I use.
Consider the following simplified JavaScript object data type:
data Object = Object [(String, Object)]
| String String
How can I defined a pretty-printing function that wraps its output to multiple lines in the usual way? What I mean by that is: the pretty-printed output should, whenever possible fit on one line. When that is not possible, I expect the outermost objects to start adding newlines before the inner ones.
Here is one attempt using wl-pprint-annotated:
{-# LANGUAGE OverloadedString #-}
import Text.PrettyPrint.Annotated.WL
prettyObject :: Object -> Doc a
prettyObject (String str) = "\"" <> text str <> "\""
prettyObject (Object fields) = Union ("{" <+> hsep fields' <+> "}")
("{" <#> indent 2 (vsep fields') <#> "}")
where
fields' :: [Doc a]
fields' = punctuate "," [ text key <> ":" <+> prettyObject val
| (key,val) <- fields ]
Now, some test cases.
ghci> o1 = Object [("key1", String "val1")]
ghci> o2 = Object [("key2", String "val2"), ("looooooooooong key3", String "loooooooooooong val3"),("key4", String "val4")]
ghci> o3 = Object [("key5", String "val5"), ("key6", o2), ("key7", String "val7")]
ghci> prettyObject o1
{ key1: "val1" }
ghci> prettyObject o2
{
key2: "val2",
looooooooooong key3: "loooooooooooong val3",
key4: "val4"
}
ghci> prettyObject o3
{ key5: { key1: "val1" }, key6: {
key2: "val2",
looooooooooong key3: "loooooooooooong val3",
key4: "val4"
}, key7: "val7" }
I would like the last output to instead be
{
key5: { key1: "val1" },
key6: {
key2: "val2",
looooooooooong key3: "loooooooooooong val3",
key4: "val4"
},
key7: "val7"
}
I am looking for a solution which somehow fits with one of the existing pretty-printing libraries in Haskell (in reality, I'm pretty-printing much more than just a subset of JSON).
I am not looking for a solution which defines a prettyObject :: Object -> String - the whole point of this approach is that the rendering of the Doc depends on where it is in the big picture of what is being pretty-printed.
The pretty print library you are using can already do this; (you have just told it to do a different thing!) generally this family (WL) of pretty printers handles this case pretty well.
Note the positioning of your Union:
prettyObject (Object fields) = Union <one line> <many line>
At the point in your text where you are logically making the choice to break, which is at the beginning of a key-value pair, you don't have a Union in your Doc structure. The choice is made at the point where a {..} enclosed block begins; and if you scrutinize the output, that is exactly what it gives you:
{ key5: { key1: "val1" }, key6: { ----- line break here
key2: "val2",
You need a function to implement your desired logic for key-value pairs:
indent' k x = flatAlt (indent k x) (flatten x)
prettyKVPair (k,v) = indent' 2 $ text k <> ":" <+> pretty v
indent' is like indent, but provides an explicit alternative which is not indented. flatAlt provides an alternative which is used when the text is flattened, and your text will be flattened by (you may have guessed) flatten. You also need to re-structure prettyObject accordingly:
prettyObject :: Object -> Doc a
prettyObject (Object fields) = sep $ "{" : fields' ++ [ "}" ] where
fields' = punctuate "," $ map prettyKVPair fields
...
Note there is no explicit Union, but sep = group . vsep and group = \x -> Union (flatten x) x. You now have a union corresponding to logical choices about where you flatten your text.
The result:
>pretty o1
{ key1: "val1" }
>pretty o2
{
key2: "val2",
looooooooooong key3: "loooooooooooong val3",
key4: "val4"
}
>pretty o3
{
key5: "val5",
key6: {
key2: "val2",
looooooooooong key3: "loooooooooooong val3",
key4: "val4"
},
key7: "val7"
}
In response to the question in the comment, the way to provide a flat alternative is to use flatAlt, of course! The only issue here is you want to do this for a single element (the last one) of a list - but this is an issue with lists, not Doc. Feel free to use Data.Sequence or any other Traversable, with which most of the 'list-like' functions like punctuate work, if this is an operation you need a lot.
flattenedOf a b = flatAlt a (flatten b) # useful combinator
trailingSep _ [] = []
trailingSep s xs = as ++ [ (a <> s) `flattenedOf` a ]
where as = init xs; a = last xs
...
prettyObject (Object fields) = <unchanged> where
fields' = trailingSep "," $ <unchanged>

Groovy way to merge two lists of maps with some calculations

I need to merge to maps while perform some calculation for example having the following maps that always will be the same size
def map1 = [
[name: 'Coord1', quota: 200],
[name: 'Coord2', quota: 300]
]
def map2 = [
[name: 'Coord1', copiesToDate: 270],
[name: 'Coord2', copiesToDate: 30]
]
I want to get this map
def map3 = [
[name: 'Coord1', quota: 200, copiesToDate: 60, balance: 140],
[name: 'Coord2', quota: 300, copiesToDate: 30, balance: 270]
]
Right now i am trying with this solution and its working
def map4 = map1.collect { m1 ->
[
name: m1.name,
quota: m1.quota,
copiesToDate: map2.find { m2 ->
m1.name == m2.name
}.copiesToDate,
balanceToDate: m1.quota - map2.find { m2 ->
m1.name == m2.name
}.copiesToDate
]}
Could you please share a groovy way to do this task. Thanks
Grooviest code I could come up with:
def map3 = [map1, map2].transpose()*.sum().each { m ->
m.balance = m.quota - m.copiesToDate
}
edit: as noted by Tim, this code works as long as the two input lists (map1 and map2) are of the same size and have the maps in order. If this is not the case I would recommend Tim's answer which handles those cases.
The above returns the map as defined in your question. The following code:
def list1 = [
[name: 'Coord1', quota: 200],
[name: 'Coord2', quota: 300]
]
def list2 = [
[name: 'Coord1', copiesToDate: 60],
[name: 'Coord2', copiesToDate: 30]
]
def x = [list1, list2].transpose()*.sum().each { m ->
m.balance = m.quota - m.copiesToDate
}
x.each {
println it
}
demonstrates the idea and prints:
[name:Coord1, quota:200, copiesToDate:60, balance:140]
[name:Coord2, quota:300, copiesToDate:30, balance:270]
I have renamed map1 and map2 into list1 and list2 since they are in fact two lists containing inner maps.
The code is somewhat concise and might need a bit of explanation if you're not used to transpose and the groovy spread and map operations.
Explanation:
[list1, list2] - first we create a new list where the two existing lists are elements. So we now have a list of lists where the elements in the inner lists are maps.
.transpose() - we then call transpose which might need a bit of effort to grasp when you see it for the first time. If you have a list of lists, you can see transpose as flipping the lists "into the other direction".
In our case the two lists:
[[name:Coord1, quota:200], [name:Coord2, quota:300]]
[[name:Coord1, copiesToDate:60], [name:Coord2, copiesToDate:30]]
become:
[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]]
[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]]
i.e. after transpose, everything relating to Coord1 is in the first list and everything relating to Coord2 is in the second.
Each of the lists we have now is a list of Maps. But what we want is just one map for Coord1 and one map for Coord2. So for each of the above lists, we now need to coalesce or merge the contained maps into one map. We do this using the fact that in groovy map+map returns a merged map. Using the groovy spread operator *. we therefore call sum() on each list of maps.
i.e.:
[[name:Coord1, quota:200], [name:Coord1, copiesToDate:60]].sum()
computes into:
[name:Coord1, quota:200, copiesToDate:60]
and:
[[name:Coord2, quota:300], [name:Coord2, copiesToDate:30]].sum()
into:
[name:Coord2, quota:300, copiesToDate:30]
lastly we want to add the balance property to the maps so we iterate through what is now a list of two maps and add balance as a computation of quota - copiesToDate. The each construct returns the list it is working on which is what we assign to x.
Don't call find twice. Use the Map.plus() method to append new entries. Handle missing names from map2.
def map3 = map1.collect {m1 ->
def m2 = map2.find {it.name == m1.name} ?: [copiesToDate: 0]
m1 + m2 + [balance: m1.quota - m2.copiesToDate]
}
Another option for fun :-)
def result = (map1 + map2).groupBy { it.name }
.values()
*.sum()
.collect { it << ['balance': it.quota - it.copiesToDate] }
add the lists together
group by the name
get the grouped values and concatenate them
then for each of them, work out the balance

P[Node].rep produces P[String] rather than array of nodes

I would expect the result for plusses to be some kind of array
case class Plus()
val plus: P[Plus] = P ("+") map {_ => Plus()}
val plusses: P[List[Plus]] = P ( plus.rep.! ) // type mismatch; found: Parser[String] required: Parser[List[Plus]]
but compiler says
type mismatch; found : Parser[String] required: Parser[List[Plus]]
Answer
First, you don't need to capture something with .! as you already have a result in the plus parser. The .rep then "creates" a parser that repeats the plus parser 0 to n times and concatenates the result into a Seq[Plus].
case class Plus()
val plus: P[Plus] = P ("+") map {_ ⇒ Plus()}
val plusses: P[Seq[Plus]] = P ( plus.rep )
Second, if using the repeat operation rep, Parsers return Seq and not List If you really need a list, use map to convert Seq to List.
val plussesAsList: P[List[Plus]] = P( plus.rep ).map( seq ⇒ seq.toList)
.! is "to capture the section of the input string the parser parsed" (see http://lihaoyi.github.io/fastparse/#Capture). So the return type of .! is String.
I think what you want is:
val plusses: P[List[Plus]] = P ( plus.rep ) map (_.toList)
Here's what you will get:
# plusses.parse("+++")
res6: core.Result[List[Plus]] = Success(List(Plus(), Plus(), Plus()),3)

Groovy: String representing a List to an actual List

Is there a way in Groovy to make a list out of a string? i.e. I have a String "[0,1]" , and I want to transform it to [0,1] (and actual groovy list) in order to manipulate.
The values of the string might be bidimensional ( "[ [1], [2, 3]]" ) but it's for sure it will always be a list.
You can use Eval.me but obviously, take care of evaluating any old strings
def a = Eval.me( '[ 1, 2 ]' )
An alternative could be:
def a = new groovy.json.JsonSlurper().parseText( '[ 1, 2 ]' )
As the two list forms you give in your question are both valid Json :-)
PERFORMANCE
Given the following benchmarking code:
#Grab('com.googlecode.gbench:gbench:0.4.1-groovy-2.1') // v0.4.1 for Groovy 2.1
import groovy.json.JsonSlurper
def r = benchmark( measureCpuTime:false ) {
'eval' {
def a = Eval.me( '[ 1, 2 ]' )
assert a == [ 1, 2 ]
}
'json' {
def a = new JsonSlurper().parseText( '[ 1, 2 ]' )
assert a == [ 1, 2 ]
}
}
r.prettyPrint()
I get the output:
eval 4661121
json 7257
So it's much quicker going the json route ;-)

python how to check list does't contain any value

consider this simple function
def foo(l=[]):
if not l: print "List is empty"
else : print "List is not empty"
Now let's call foo
x=[]
foo(x)
#List is empty
foo('')
#List is empty
But if x=[''] the list is not considered as empty!!!
x=['']
foo(x)
#List is not empty
Questions -
Why list of empty values are not considered as empty? (In case of variable it is considered as empty e.g.)
x=''
if x:print 'not empty!!'
else: print 'empty'
How can I modify function foo() so that list will be considered as empty in all these cases: x=[] , x=[''], x=['', '']
Using the built-in any()
def foo(l=[]):
if any(l):
print 'List is not empty'
else:
print 'List is empty'
foo([''])
# List is empty
In your examples, the only case where the list really is empty is the one in which there is nothing in the square brackets. In the other examples you have lists with various numbers of empty strings. These are simply different (and in all languages I can think of, the same would be true).
You can use recursive call to the function foo to deal with nested lists.
def foo(l=[]):
if type(l)==list:
return any([foo(x) for x in l])
else:
return bool(l)
First of all: Even an empty string is a string. A list that contains an empty string still contains an element.
while a='' is empty with len = 0, it is regardless for the list, it still contains an element, e.g., mylist = [a] is the same as mylist = [''] but it might be clearer to you. Take a as an element and ignore the content.
To check if elements of a list are empty, iterate over them.
def isEmpty(li=[]):
for elem in li:
if len(elem) > 0: return false
return true
To answer your first question about why a list of empty values is not considered empty, it's because it does contain something, even if those things are themselves empty. Think of it like a box of empty boxes.
The code below shows one way to modify the function foo() to do what you want (and test it). Your notion of what an empty list is was surprisingly tricky to devise, partially because it runs counter to what the language itself considers empty. As you can see all the logic dealing with the determination of whether the list is "empty" according to your definition has been moved into a separate function called empty_list() since that probably has little to do with the rest of what foo() has to accomplish. It's not overly complex and if nothing else should provide you with a good starting point.
Also, you didn't say what it should do if the argument it's passed isn't a list of any kind or was a list but didn't contain just other lists or strings, so as written it will raise a TypeError exception -- something which is similar to the way most built-in Python functions respond when this occurs with them. Below is the sample code and its test output:
try:
string_type = basestring
except NameError: # probably Python 3.x
string_type = str
class _NULL(object): # unique marker object
def __repr__(self): return '<nothing>'
_NULL = _NULL()
def empty_list(arg=_NULL):
arg = arg if arg is not _NULL else []
if not isinstance(arg, (list, string_type)):
raise TypeError
elif isinstance(arg, string_type):
return not len(arg)
else:
return len(arg) == 0 or all(empty_list(e) for e in arg)
def foo(list_=None):
if list_ is None or empty_list(list_):
print 'list is empty'
else:
print 'list is not empty'
testcases = [
_NULL,
[],
[''],
['', ''],
['', ['']],
['abc'],
['', 'abc'],
[False],
[None],
[0],
[0.0],
[0L],
[0j],
[42],
[{}],
[{'':0}],
[{'a':1}],
False,
None,
0,
0.0,
0L,
0j,
42,
{},
{'':0},
{'a':1},
]
for arg in testcases:
call = 'foo( {!r:s} ) ->'.format(arg)
print '{!s:>20s}'.format(call),
try:
foo() if arg is _NULL else foo(arg)
except TypeError:
print 'illegal argument exception'
Here's the output it produces with Python 2.7:
foo( <nothing> ) -> list is empty
foo( [] ) -> list is empty
foo( [''] ) -> list is empty
foo( ['', ''] ) -> list is empty
foo( ['', ['']] ) -> list is empty
foo( ['abc'] ) -> list is not empty
foo( ['', 'abc'] ) -> list is not empty
foo( [False] ) -> illegal argument exception
foo( [None] ) -> illegal argument exception
foo( [0] ) -> illegal argument exception
foo( [0.0] ) -> illegal argument exception
foo( [0L] ) -> illegal argument exception
foo( [0j] ) -> illegal argument exception
foo( [42] ) -> illegal argument exception
foo( [{}] ) -> illegal argument exception
foo( [{'': 0}] ) -> illegal argument exception
foo( [{'a': 1}] ) -> illegal argument exception
foo( False ) -> illegal argument exception
foo( None ) -> list is empty
foo( 0 ) -> illegal argument exception
foo( 0.0 ) -> illegal argument exception
foo( 0L ) -> illegal argument exception
foo( 0j ) -> illegal argument exception
foo( 42 ) -> illegal argument exception
foo( {} ) -> illegal argument exception
foo( {'': 0} ) -> illegal argument exception
foo( {'a': 1} ) -> illegal argument exception
The list [''] is, indeed, not empty. It contains an empty string. The string is empty, the list is not. If you want to find these lists, check if the list is empty, and if not, check if every entry is ''.

Resources