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.
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
data Task = Task
{ id :: String
, description :: String
, dependsOn :: [String]
, dependentTasks :: [String]
} deriving (Eq, Show, Generic, ToJSON, FromJSON)
type Storage = Map String Task
s :: Storage
s = empty
addTask :: Task -> Storage -> Storage
addTask (Task id desc dep dept) = insert id (Task id desc dep dept)
removeTask :: String -> Storage -> Storage
removeTask tid = delete tid
changes = [addTask (Task "1" "Description" [] []), removeTask "1"]
main = putStrLn . show $ foldl (\s c -> c s) s changes
Suppose I have the following code. I want to store changes list in a json file. But I don't know how to do that with Aeson, aside probably from writing a custom parser and there must be a better way to do that obviously. Like maybe using language extension to derive (Generic, ToJSON, FromJSON) for addTask and removeTask etc...
EDIT. For all people that say "You can't serialize function".
Read the comments to an answer to this question.
Instance Show for function
That said, it's not possible to define Show to actually give you more
? detail about the function. – Louis Wasserman May 12 '12 at 14:51
Sure it is. It can show the type (given via Typeable); or it can show some of the inputs and outputs (as is done in QuickCheck).
EDIT2. Okay, I got that I can't have function name in serialization. But can this be done via template Haskell? I see that aeson supports serialization via template Haskell, but as newcomer to Haskell can't figure out how to do that.
Reading between the lines a bit, a recurring question here is, "Why can't I serialize a function (easily)?" The answer -- which several people have mentioned, but not explained clearly -- is that Haskell is dedicated to referential transparency. Referential transparency says that you can replace a definition with its defined value (and vice versa) without changing the meaning of the program.
So now, let's suppose we had a hypothetical serializeFunction, which in the presence of this code:
foo x y = x + y + 3
Would have this behavior:
> serializeFunction (foo 5)
"foo 5"
I guess you wouldn't object too strenuously if I also claimed that in the presence of
bar x y = x + y + 3
we would "want" this behavior:
> serializeFunction (bar 5)
"bar 5"
And now we have a problem, because by referential transparency
serializeFunction (foo 5)
= { definition of foo }
serializeFunction (\y -> 5 + y + 3)
= { definition of bar }
serializeFunction (bar 5)
but "foo 5" does not equal "bar 5".
The obvious followup question is: why do we demand referential transparency? There are at least two good reasons: first, it allows equational reasoning like above, hence eases the burden of refactoring; and second, it reduces the amount of runtime information that's needed, hence improving performance.
Of course, if you can come up with a representation of functions that respects referential transparency, that poses no problems. Here are some ideas in that direction:
printing the type of the function
instance (Typeable a, Typeable b) => Show (a -> b) where
show = show . typeOf
-- can only write a Read instance for trivial functions
printing the input-output behavior of the function (which can also be read back in)
creating a data type that combines a function with its name, and then printing that name
data Named a = Named String a
instance Show (Named a) where
show (Named n _) = n
-- perhaps you could write an instance Read (Map String a -> Named a)
(and see also cloud haskell for a more complete working of this idea)
constructing an algebraic data type that can represent all the expressions you care about but contains only basic types that already have a Show instance and serializing that (e.g. as described in the other answer)
But printing a bare function's name is in conflict with referential transparency.
Make a data type for your functions and an evaluation function:
data TaskFunction = AddTask Task | RemoveTask String
deriving (Eq, Show, Generic, ToJSON, FromJSON)
eval :: TaskFunction -> Storage -> Storage
eval (AddTask t) = addTask t
eval (RemoveTask t) = removeTask t
changes = [AddTask (Task "1" "Description" [] []), RemoveTask "1"]
main = putStrLn . show $ foldl (\s c -> c s) s (eval <$> changes)
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).
Imagine I have a custom type and two functions:
type MyType = Int -> Bool
f1 :: MyType -> Int
f3 :: MyType -> MyType -> MyType
I tried to pattern match as follows:
f1 (f3 a b i) = 1
But it failed with error: Parse error in pattern: f1. What is the proper way to do the above?? Basically, I want to know how many f3 is there (as a and b maybe f3 or some other functions).
You can't pattern match on a function. For (almost) any given function, there are an infinite number of ways to define the same function. And it turns out to be mathematically impossible for a computer to always be able to say whether a given definition expresses the same function as another definition. This also means that Haskell would be unable to reliably tell whether a function matches a pattern; so the language simply doesn't allow it.
A pattern must be either a single variable or a constructor applied to some other patterns. Remembering that constructor start with upper case letters and variables start with lower case letters, your pattern f3 a n i is invalid; the "head" of the pattern f3 is a variable, but it's also applied to a, n, and i. That's the error message you're getting.
Since functions don't have constructors, it follows that the only pattern that can match a function is a single variable; that matches all functions (of the right type to be passed to the pattern, anyway). That's how Haskell enforces the "no pattern matching against functions" rule. Basically, in a higher order function there's no way to tell anything at all about the function you've been given except to apply it to something and see what it does.
The function f1 has type MyType -> Int. This is equivalent to (Int -> Bool) -> Int. So it takes a single function argument of type Int -> Bool. I would expect an equation for f1 to look like:
f1 f = ...
You don't need to "check" whether it's an Int -> Bool function by pattern matching; the type guarantees that it will be.
You can't tell which one it is; but that's generally the whole point of taking a function as an argument (so that the caller can pick any function they like knowing that you'll use them all the same way).
I'm not sure what you mean by "I want to know how many f3 is there". f1 always receives a single function, and f3 is not a function of the right type to be passed to f1 at all (it's a MyType -> MyType -> MyType, not a MyType).
Once a function has been applied its syntactic form is lost. There is now way, should I provide you 2 + 3 to distinguish what you get from just 5. It could have arisen from 2 + 3, or 3 + 2, or the mere constant 5.
If you need to capture syntactic structure then you need to work with syntactic structure.
data Exp = I Int | Plus Exp Exp
justFive :: Exp
justFive = I 5
twoPlusThree :: Exp
twoPlusThree = I 2 `Plus` I 3
threePlusTwo :: Exp
threePlusTwo = I 2 `Plus` I 3
Here the data type Exp captures numeric expressions and we can pattern match upon them:
isTwoPlusThree :: Exp -> Bool
isTwoPlusThree (Plus (I 2) (I 3)) = True
isTwoPlusThree _ = False
But wait, why am I distinguishing between "constructors" which I can pattern match on and.... "other syntax" which I cannot?
Essentially, constructors are inert. The behavior of Plus x y is... to do nothing at all, to merely remain as a box with two slots called "Plus _ _" and plug the two slots with the values represented by x and y.
On the other hand, function application is the furthest thing from inert! When you apply an expression to a function that function (\x -> ...) replaces the xes within its body with the applied value. This dynamic reduction behavior means that there is no way to get a hold of "function applications". They vanish into thing air as soon as you look at them.