I am currently trying to figure out a way to writer a "telephone book". (It's a task from university so I would appreciate a tip rather than a full solution)
I created a function which enables the user to write in several names as follows:
(It had to be solves like this, because we had to use type TelephoneBook = String -> String)
(enterName "Peter" "4232" (enterName "Alice" "23213" emptyBook)) ""
This would then return Peter.
Well now I am supposed to be able to access this data and search for a name and then retrieve a Number.
My current Idea is as follows:
searchFkt :: String -> TelephoneBook -> String
searchFkt a b
| (a == book "") = a --Iam fully aware that this doesn't work
| otherwise = "not found"
I am aware that the second part doesn't work like that (searchFkt :: String -> TelephoneBook -> String was given as well), however I have no clue how to implement this and I really need help, because I have been looking through books and trying to wrap myself around how to solve this for hours.
Thanks in advance
Ps: I want to understand how this works and not just have a solution, so maybe a reference to what to read would be helpful as well :)
This isn't an answer, per se, but an attempt to clarify what your assignment appears to be, both for your sake and the sake of others trying to read your question(s).
The ultimate goal of your assignment appears to be to implement a phone book using a function; a hard-coded example might be
type TelephoneBook = String -> String
myPhoneBook :: TelephoneBook
myPhoneBook "Peter" = "4232"
myPhoneBook "Alice" = "23213"
Note that this is only a partial function; it is not defined at all for the vast majority of possible names.
One problem with this approach is that it doesn't allow for a truly empty phone book, since you can't define a function that doesn't actually do anything. So, we'll replace that with an "empty" book that returns a default value for any name not already in the phone book:
-- Not ideal, but it's the best we can do given the constraints
-- imposed by the given type.
empty :: TelephoneBook
empty _ = "not found"
Your goal is to write a function enterName that takes a name, a phone number, and an existing phone book, and returns a new phone book that is the same as the old one, but with one new entry (that overrides any previous entry with the same name. That is,
empty "Peter" == "not found"
(enterName "Peter" "1234" empty) "Peter" == "1234"
(enterName "Peter" "1234" empty) "Bob" == "not found"
(enterName "Bob" "9876" (enterName "Peter" "1234" empty)) "Bob" == "9876"
Your enterName function has type String -> String -> TelephoneBook -> TelephoneBook, meaning it takes three arguments, and it needs to actually do something with all three of them.
enterName :: String -> String -> TelephoneBook -> TelephoneBook
enterName name number phonebook = ...
Likewise, your searchFkt :: String -> TelephoneBook -> String function takes a name and a phone book and returns the number associated with that name in the book.
searchFkt :: String -> TelephoneBook -> String
searchFkt name book = ...
Given the definition of TelephoneBook above and the examples of its use, it should be obvious how to implement searchFkt.
Given that you say Telephonebook is a type alias String -> String, I think you want to compose a function that maps names onto telephone number. So that if you lookup "Peter" from the book, it returns "4232".
Now if you want to search for a name, all you have to do is call the query on the telephonebook. So searchFkt would look like:
searchFkt :: String -> Telephonebook -> String
searchFkt query book = book query
Nevertheless based on your comments, I think you made an error in your enterName program. Here you say you implemented it as:
putName :: String -> String -> Telephonebook -> Telephonebook
putName name number oldbook = \x -> number
(I took the liberty to rename a, b and c.). As you can see, name and oldbook are not even mentioned in the right side of the expression. As a result Haskell forgets about these: it thus means that nor name, nor oldbook play any part in the construction of the new book.
A better way would be to implement it as:
putName :: String -> String -> Phonebook -> Phonebook
putName name number oldbook = newbook
where newbook query | query == name = number
| otherwise = oldbook query
In other words you construct a new function newbook that takes as input a query (the name you are supposed to resolve). In case query is equal to the given new name, it returns the number; otherwise it asks the oldbook to handle it further.
Finally I think it is not a good idea to implement the phonebook as a function String -> String, because a next task might be to implement a reverse lookup operation, in which case you are lost. It is better to implement it as a list of tuples like [(String,String)] (of course hashmaps, etc. would be more ideal).
Related
I am trying to define a parser in Haskell. I am a total beginner and somehow didn't manage to find any solution to my problem at all.
For the first steps I tried to follow the instructions on the slides of a powerpoint presentation. But I constantly get the error "Not in scope: type variable ‘a’":
type Parser b = a -> [(b,a)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x:xs)]
error: Not in scope: type variable ‘a’
|
11 | type Parser b = a -> [(b,a)]
| ^
I don't understand the error but moreover I don't understand the first line of the code as well:
type Parser b = a -> [(b,a)]
What is this supposed to do? On the slide it just tells me that in Haskell, Parsers can be defined as functions. But that doesn't look like a function definition to me. What is "type" doing here? If it s used to specify the type, why not use "::" like in second line above? And "Parser" seems to be a data type (because we can use it in the type definition of "item"). But that doesn't make sense either.
The line derives from:
type Parser = String -> (String, Tree)
The line I used in my code snippet above is supposed to be a generalization of that.
Your help would be much appreciated. And please bear in mind that I hardly know anything about Haskell, when you write an answer :D
There is a significant difference between the type alias type T = SomeType and the type annotation t :: SomeType.
type T = Int simply states that T is just another name for the type Int. From now on, every time we use T, it will be replaced with Int by the compiler.
By contrast, t :: Int indicates that t is some value of type Int. The exact value is to be specified by an equation like t = 42.
These two concepts are very different. On one hand we have equations like T = Int and t = 42, and we can replace either side with the other side, replacing type with types and values with values. On the other hand, the annotation t :: Int states that a value has a given type, not that the value and the type are the same thing (which is nonsensical: 42 and Int have a completely different nature, a value and a type).
type Parser = String -> (String, Tree)
This correctly defines a type alias. We can make it parametric by adding a parameter:
type Parser a = String -> (String, a)
In doing so, we can not use variables in the right hand side that are not parameters, for the same reason we can not allow code like
f x = x + y -- error: y is not in scope
Hence you need to use the above Parser type, or some variation like
type Parser a = String -> [(String, a)]
By contrast, writing
type Parser a = b -> [(b, a)] -- error
would use an undeclared type b, and is an error. At best, we could have
type Parser a b = b -> [(b, a)]
which compiles. I wonder, though, is you really need to make the String type even more general than it is.
So, going back to the previous case, a possible way to make your code run is:
type Parser a = String -> [(a, String)]
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x, xs)]
Note how [(x, xs)] is indeed of type [(Char, String)], as needed.
If you really want to generalize String as well, you need to write:
type Parser a b = b -> [(b, a)]
item :: Parser Char String
item = \inp -> case inp of
[] -> []
(x:xs) -> [(xs, x)]
Suppose I have a function that takes 3 parameters as input. How to partially apply this function in Elm so it takes first and last parameters and waits for the second parameter to return the final result?
This can be done in Ramda with R.__ which is named placeholer.
You can just wrap it in a lambda function that has the shape you want, which is what would be produced by any other means anyway:
\y -> f "x" y "z"
In a curried language I find the need to do this so rare that adding syntax sugar specifically for this use case seems unnecessary.
As glennsl says, you can wrap your function in another function with the argument order that you want. his answer assumes that you know statically what the first and third arguments are, if you don't, but just want to partially apply the first and third argument, then apply the second you can take a function like,
joinThree : String -> String -> String -> String
joinThree first second third =
first ++ second ++ third
and wrap it in a new function that calls the first function, but with a different argument order,
joinThreeWrapper : String -> String -> String -> String
joinThreeWrapper first third second =
joinThree first second third
This allows you to call this function like,
welcomeToNeverland : String -> String
welcomeToNeverland name =
let
myGreeting = joinThreeWrapper "Welcome " " to Neverland"
in
myGreeting name
Then you can use it like,
text (welcomeToNeverland "Wendy")
-- Welcome Wendy to Neverland
Writing joinThreeWrapper like this makes it a bit easier to map your function over a list like,
greetMany : List String -> List String
greetMany names =
List.map (joinThreeWrapper "Welcome " ", this is our town. ") names
so that you can do,
text (List.map (++) (greetMany ["Jesse", "Carl"]))
-- Welcome Jesse, this is our town. Welcome Carl, this is our town.
You can use flip from the core Basics module.
For instance:
> append3 x y z = x ++ y ++ z
<function> : appendable -> appendable -> appendable -> appendable
> hello = flip (append3 "Hello, ") "!"
<function> : String -> String
> hello "world"
"Hello, world!" : String
we are currently sitting on a task from university, which we don't fully understand (please no solution but only ideas or suggestions).
What is given is a type:
type MyType = String -> String
Now we are trying to be able to have a function, which takes 2 Strings and a function (the type) and then gives a function (type)
myCode :: String -> String -> MyType -> MyType
and we already implemented a function, which can be used as MyType one:
emptyString :: MyType
emptyString :: (\a -> "")
The task is to be able to store several 2x Strings. This is our current idea:
myCode :: String -> String -> MyType ->MyType
myCode a b c = (\x -> b)
in this case we have an input String, which is "Hello" and another one which is "World" and then as c we put in the "emptyString".
This works for one String, because when we type the following in the console:
a = (myCode "Hello" "World" emptyString) ""
we get "World" on input "a". Now the hard part: We should be able to store several of these (searching them is another task, not needed right now). We thought we might be able to use "a" now when declaring another variable:
b = (myCode "1" "2" a) "Hello" "World" emptyString "")
This would call in "b" the function saved as "a" and within this the "emptyString".
As you may have guessed - it doesn't work! And we are really at a loss on how to carry on from now.
When you reached this part, it means you took the time to understand our complicated explanation of our task - thanks a lot.
Thanks for suggestions and help in advance!
From the question linked by amalloy in the comments, it looks like you are trying to build a phonebook based on a continuation passing style like paradigm.
Basically, what is supposed to happen for your type
myCode :: String -> String -> MyType -> MyType
is that you will generate a piece of data dat = myCode a b pb, which is of type MyType. So, you can query dat with an s :: String and it will output another String. In the operation of dat s, if you expand it to the definition,
dat s = myCode a b pb s
you have access to three strings, a, b, and whatever pb s returns. You will build up functionality recursively, either by doing something with a b and s, or pushing it down the road to pb, letting the continuation handle it.
Hope this helps without giving too much away.
I'm programming in Haskell and have the following type.
type Phonebook = String -> String
Now I have to create a function that returns an empty Phonebook, so
emptyPhonebook :: Phonebook
emptyPhonebook = ???
But what is an empty Phonebook?
I mean it has to be an "empty" function, but how do I write that in Haskell?
There is no such thing as an empty function.
The question is, what should your phonebook return for names that aren't in the phone book?
If this is a learning exercise, you could just return an empty string - as in the other answer.
However, a better definition of your phonebook would be:
type Phonebook = String -> Maybe String
Then your function becomes:
emptyPhoneBook :: Phonebook
emptyPhoneBook _ = Nothing
This is like using nullable types in languages like C#; the Maybe says that your value can either be a String, or Nothing.
For completeness, I should add that if Maybe String contains a string value, its value will be preceded by the keyword Just.
For example, if the String in question was "Judie", the value would be Just "Judie" rather than merely "Judie".
The Just is because the value is of type Maybe String, not of type String.
I does not have to be an empty funtion, it has to be a String->String function, even id would do
emptyPhonebook :: Phonebook
emptyPhonebook = \_ -> ""
Take a look at this running example:
My current project involves lexing and parsing script code, and as such I'm using fslex and fsyacc. Fslex LexBuffers can come in either LexBuffer<char> and LexBuffer<byte> varieties, and I'd like to have the option to use both.
In order to user both, I need a lexeme function of type ^buf -> string. Thus far, my attempts at specialization have looked like:
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: char array) =
new System.String(lexbuf.Lexeme)
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: byte array) =
System.Text.Encoding.UTF8.GetString(lexbuf.Lexeme)
I'm getting a type error stating that the function body should be of type ^buf -> string, but the inferred type is just string. Clearly, I'm doing something (majorly?) wrong.
Is what I'm attempting even possible in F#? If so, can someone point me to the proper path?
Thanks!
Functions and members marked as inline cannot be overloaded, so your original strategy won't work. You need to write different code for both of the declarations, so you need to use overloading (if you want to write this without boxing and dynamic type tests).
If you're using standard F# tools, then the type you'll get as a buffer will always be LexBuffer<'T> and you want to have two overloads based on the type argument. In this case, you don't need the static member constraints at all and can write just:
type Utils =
static member lexeme(buf:LexBuffer<char>) =
new System.String(buf.Lexeme)
static member lexeme(buf:LexBuffer<byte>) =
System.Text.Encoding.UTF8.GetString(buf.Lexeme)
Are you sure this strategy of redefining inline functions with different argument types can work? Looks like you're trying to overload to me...
type LexBuffer<'a>(data : 'a []) =
member this.Lexeme = data
let lexeme (buf : LexBuffer<'a>) =
match box buf.Lexeme with
| :? (char array) as chArr ->
new System.String(chArr)
| :? (byte array) as byArr ->
System.Text.Encoding.UTF8.GetString(byArr)
| _ -> invalidArg "buf" "must be either char or byte LexBuffer"
new LexBuffer<byte>([| 97uy; 98uy; 99uy |])
|> lexeme
|> printfn "%A"
new LexBuffer<char>([| 'a'; 'b'; 'c' |])
|> lexeme
|> printfn "%A"