Using perfectly formatted input as list in Haskell - haskell

I'm doing a program in Haskell (on the Haskell platform), and I know I'm getting perfectly formatted inputs, so the input may look like
[ ['a'], ['b'], ['c'] ]
I want Haskell to be able to take this and use it as a list of it's own. And, I'd like this list to be over multiple lines, i.e., I want this to also work:
[
['a'],
['b'],
['c']
]
I can parse this input, but I've been told there's a way to do this easily - this is supposed to be the 'trivial' part of the assignment, but I don't understand it.

read "[ ['a'], ['b'], ['c'] ]" :: [[Char]]
will return [ ['a'], ['b'], ['c'] ]. If you assign the result of read to a variable that can be inferred to be of type [[Char]], you don't need the :: [[Char]] bit.

There is an instance of the Read class for Haskell lists, meaning you can use the read function to effectively parse strings formatted like Haskell lists, which is exactly what you have.

Related

Interpolate without creating a String context in Raku?

If I have a variable my $a = True, then I get this output from the following code:
say «a list of words foo $a bar baz».raku;
# OUTPUT: ("a", "list", "of", "words", "foo", "True", "bar", "baz")
That is, even though the result is a List, the element True is stringified before being included in the list – the list contains "True", not True. Is there any way to avoid that stringification while still using interpolation?
Would there be a way to do so if $a were a class I'd defined (and thus can write the Str method for) rather than a Bool?
(I am aware that I can write the more verbose ("a", "list", "of", "words", "foo", $a, "bar", "baz") or «a list of words foo».Slip, $a, «bar baz».Slip, but I'm asking if there is a way to still use interpolation).
Interpolation is putting a thing into a string.
"a b c $thing d e f"
It does that by first turning the thing itself into a string, and concatenating the rest of the string around it.
Basically the above compiles into this code:
infix:<~>( 「a b c 」, $thing.Str, 「 d e f」 )
« a b c $thing »
Is short for:
Q :double :quotewords « a b c $thing d e f »
That is use the Quoting DSL, turning on :double quote semantics (“”) and turning on :quotewords.
:quotewords is the feature which splits the string into its individual parts.
It happens only after it has been turned into a string.
Imagine that the above compiles into:
Internals::quotewords( infix:<~>( 「 a b c 」, $thing.Str, 「 d e f 」 ) )
There is another way to get what you want, other than using .Slip or prefix |.
flat «a list of words foo», $a, «bar baz»
The whole purpose of the quoting DSL is that it produces a string.
That said :words, :quotewords, and :val all change it so that it returns something other than a single string.
And the idea of them is that they alter the DSL.
So MAYBE you could convince enough people that such a change would be worth it.
Thats a big maybe.
It would potentially break many existing codebases, so you would have an uphill battle to do so.
What happens here has little to do with quoting, and a lot to do with context. As #brad-gilbert has indicated, anything that goes passes through putting ~ in front, which is coercing the variable to a String context.
But that yields an answer to your second question:
Would there be a way to do so if $a were a class I'd defined (and thus can write the Str method for) rather than a Bool?
Theoretically, something like this should work:
class A {
has Bool $.foo;
method Str { $.foo }
};
my $a = A.new( :foo(True) );
say «a b $a».raku
Alas, this returns «No such method 'WORDS_AUTODEREF' for invocant of type 'Bool'␤ so it probably needs a bit of work (or I might have bumped into some bug). So this is, for the time being, and for your precise example, a nanswer. As a matter of fact, only Strs have that method, so I think that for the time being, and unless you bother to create that specialized method for a class, it's difficult to do.

Haskell: How to delete the same function and concatenate two lists

I am the beginner of haskell. I want to delete some same functions in the same list and concatenate the two list get together.
For example:
db1 = ["David","worksfor.isa", "IBM" ]
db2 = ["David","isa'.worksfor'", "IBM"]
db3 = ["Tom","worksfor.isa", "IBM" ]
the program can be known that "isa'.worksfor' and "worksfor.isa" is the same String. And then use "Concat" to get the new db: db1 =["David","worksfor.isa", "IBM" ] and the others: db3 = ["Tom","worksfor.isa", "IBM" ]
(map (\(a,b,c) -> concat (map(\(a',b',c') -> if ( a b == b' a') then [] else [(a,b ++ "." ++ b',c')])))) ??????
I want to "split the string, if there are ' characters, reverse it, then remove ' characters and check for equivalence"
This should be a comment, but it is far too long:
I assume you find it hard to express yourself in English. I can relate to that; I find it hard myself. However, beyond English there are two other ways to communicate here:
Using precise technical terms.
Using several, diverse examples. A single example will not suffice, and several examples which are too similar give little information.
As for option 1, you are using the wrong terminology. It is not easy for me to see how can a list with 3 items can be considered a database (as hinted by the names db1, db2). Perhaps you wanted to use a list of triples?
[ ("David","isa'.worksfor'", "IBM") ]
You are not specific about what exactly do you want to concatenate, but the term concatenation always refers to an operation that must be "additive", i.e. length(x ++ y) == length(x) ++ length(y). This does not seem to be the case in your question.
Do you want a union of two databases (lists of triples) up to equivalence?
You want the program to understand that
"isa'.worksfor'" and "worksfor.isa" are the same string
But they are not. They might be equivalent strings. You can generally do that using a map operation, like you tried, but you should note that the character ' is not an operation over strings. So a b == b' a' does nothing close to what you want - it calls the function a on the variable b, and compares this with calling the function b' over the variable a'. I can only assume you want something like "split the string, if there are ' characters, reverse it, then remove ' characters and check for equivalence" but this is completely a guesswork.
To conclude:
Please explain in detail what is the general problem you are trying to solve. Try to find the precise terms; it is difficult, but this way you can learn.
Please add different examples of input and output
Please try to explain what have you tried and where are you stuck
As a last tip, maybe you want to solve this problem in a more forgiving language than Haskell (such as JavaScript, Python, Ruby, etc.)

How to verify if some items are in a list?

I'm trying to mess about trying the haskell equivalent of the 'Scala One Liners' thing that has recently popped up on Reddit/Hacker News.
Here's what I've got so far (people could probably do them a lot better than me but these are my beginner level attempts)
https://gist.github.com/1005383
The one I'm stuck on is verifying if items are in a list. Basically the Scala example is this
val wordlist = List("scala", "akka", "play framework", "sbt", "typesafe")
val tweet = "This is an example tweet talking about scala and sbt."
(words.foldLeft(false)( _ || tweet.contains(_) ))
I'm a bit stumped how to do this in Haskell. I know you can do:
any (=="haskell") $ words "haskell is great!"
To verify if one of the words is present, but the Scala example asks if any of the words in the wordlist are present in the test string.
I can't seem to find a contains function or something similar to that. I know you could probably write a function to do it but that defeats the point of doing this task in one line.
Any help would be appreciated.
You can use the elem function from the Prelude which checks if an item is in a list. It is commonly used in infix form:
Prelude> "foo" `elem` ["foo", "bar", "baz"]
True
You can then use it in an operator section just like you did with ==:
Prelude> let wordList = ["scala", "akka", "play framework", "sbt", "types"]
Prelude> let tweet = "This is an example tweet talking about scala and sbt."
Prelude> any (`elem` wordList) $ words tweet
True
When you find yourself needing a function, but you don't know the name, try using Hoogle to search for a function by type.
Here you wanted something that checks if a thing of any type is in a list of things of the same type, i.e. something of a type like a -> [a] -> Bool (you also need an Eq constraint, but let's say you didn't know that). Typing this type signature into Hoogle gives you elem as the top result.
How about using Data.List.intersect?
import Data.List.intersect
not $ null $ intersect (words tweet) wordList
Although there are already good answers I thought it'd be nice to write something in the spirit of your original code using any. That way you get to see how to compose your own complex queries from simple reusable parts rather than using off-the-shelf parts like intersect and elem:
any (\x -> any (\y -> (y == x)) $ words "haskell is great!")
["scala", "is", "tolerable"]
With a little reordering you can sort of read it in English: is there any word x in the sentence such that there is any y in the list such that x == y? It's clear how to extend to more 'axes' than two, perform comparisons other than ==, and even mix it up with all.

Accessing a Specific Element in a Tuple

Haskell-newbie reporting in.
Question is as follows:
In Haskell, we have fst and snd that return the first and the second elements of a 2-tuple. Why don't we have an easy way of accessing the i-th element from any tuple? Right now I have a 3-tuple, I want to read the 1st element and the only way of accomplishing this task is doing pattern-matching trickery. Why can't this be done easier? Or maybe there is some easy way?
What prevents the language from having the special construct you want is its design. The designers just didn't put this in, because it would complicate the language definition, which is quite minimalistic. fst and snd are library functions for the common case of pairs; you can define all the others yourself, or better, define record types for your data so that your data members have appropriate names.
(It may be that GHC has an extension to do this, but I haven't encountered one; check the docs or ask on the mailing list to be sure.)
Check out the tuple library on hackage. It has overloaded functions for various operations on tuples (up to a predefined size).
N-tuples are not a data structure for indexing via an Int key, instead, you should look at one indexed-biased data structures, such as arrays or finger-trees.
Now, one could imagine writing a typeclass for a family of tuple types providing an index operation, however, we already have arrays for that, and there's a lot of boilerplate necessary to make tuples of any type seamlessly provide this operation. The power gained isn't worth the effort.
Why can't this be done easier? Or maybe there is some easy way?
It can be easier using a recent alternative the
lens package. The Tuple module has selectors for up to 9 element tuples and it is straight forward to define more if needed.
> import Control.Lens
> data A = A deriving (Show)
> (1, '2', "3", A) ^. _1
1
> (1, '2', "3", A) ^. _2
'2'
> (1, '2', "3", A) ^. _3
"3"
> (1, '2', "3", A) ^. _4
A
You can also use the
lens package to update elements polymorphically, change type on update.
With and without infix operators:
> (1, '2', "3", A) & _1 .~ "wow"
("wow",'2',"3",A)
> set _1 "wow" (1, '2', "3", A)
("wow",'2',"3",A)
The github readme is a good place to start to find out more about the underlying theory as well as numerous examples.
Not just tuples
Similar syntax works for Traverables and Foldables, so Trees, Maps, Vectors, etc. For example if I had a list of tuples I can access the third tuple element at the 1 index by composing the element 1 to access the first index element with _3 to access the third tuple element.
[(1,2,3),(4,5,6),(7,8,9)] ^? element 1 . _3
Just 6
The question of an approach to doing this using template haskell was previously addressed here.
An example of its usage:
> $(sel 2 3) ('a','b','c')
'b'
> $(sel 3 4) ('a','b','c','d')
'c'
From here.
cabal update
cabal install tuple
ghci
λ> import Data.Tuple.Select
λ> sel3 (0, "1", 2) --select the third element
Nikita Volkov's new "record" library has a feature that appears to do what you want. Search for the heading "Tuples are records too!" on the linked page.
It looks like the library is still under development, so it may not be as easy to install and use right now as it will be in the future.

Haskell: Delimit a string by chosen sub-strings and whitespace

Am still new to Haskell, so apologize if there is an obvious answer to this...
I would like to make a function that splits up the all following lists of strings i.e. [String]:
["int x = 1", "y := x + 123"]
["int x= 1", "y:= x+123"]
["int x=1", "y:=x+123"]
All into the same string of strings i.e. [[String]]:
[["int", "x", "=", "1"], ["y", ":=", "x", "+", "123"]]
You can use map words.lines for the first [String].
But I do not know any really neat ways to also take into account the others - where you would be using the various sub-strings "=", ":=", "+" etc. to break up the main string.
Thank you for taking the time to enlighten me on Haskell :-)
The Prelude comes with a little-known handy function called lex, which is a lexer for Haskell expressions. These match the form you need.
lex :: String -> [(String,String)]
What a weird type though! The list is there for interfacing with a standard type of parser, but I'm pretty sure lex always returns either 1 or 0 elements (0 indicating a parse failure). The tuple is (token-lexed, rest-of-input), so lex only pulls off one token. So a simple way to lex a whole string would be:
lexStr :: String -> [String]
lexStr "" = []
lexStr s =
case lex s of
[(tok,rest)] -> tok : lexStr rest
[] -> error "Failed lex"
To appease the pedants, this code is in terrible form. An explicit call to error instead of returning a reasonable error using Maybe, assuming lex only returns 1 or 0 elements, etc. The code that does this reliably is about the same length, but is significantly more abstract, so I spared your beginner eyes.
I would take a look at parsec and build a simple grammar for parsing your strings.
how about using words .)
words :: String -> [String]
and words wont care for whitespaces..
words "Hello World"
= words "Hello World"
= ["Hello", "World"]

Resources