XMonad: How to write functions involving the `Query` datatype? - haskell

Problem
I have a feeling that the reason for this question is going to ultimately come down to me just being new at/not understanding Haskell, so I'll try to be as detailed as I can with my description, to make it somewhat generic.
I am using a custom XMonad config as my window manager, defined in a file xmonad.hs.
The XMonad manageHook is what I use to handle when certain applications need to open in a certain type of window or on a certain workspace, etc.
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
Currently, a bunch of lines in my manageHook in xmonad.hs look like this:
className =? "xxxx" --> doSomething
Here is my current understanding of the line above:
These expressions involve the value of className, defined in XMonad.Hooks.ManageHook, which is of the Query type (Query [Char], to be more specific).
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
Query is defined in XMonad.Core. https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-Core.html#t:Query
=? takes the Query [Char] on the left and the [Char] literal on the right and returns a value of type Query Bool; the value will be True if the [Char]s are equal and False otherwise (I think?)
--> takes the Query Bool on the left and an action on the right and executes the action if the value of the Query Bool is True.
https://hackage.haskell.org/package/xmonad-0.17.0/docs/XMonad-ManageHook.html
However, this is only useful to me when I know the exact class name of an application I want to apply a rule to, which is not always the case. So, I took a look at xmonad-contrib to get some ideas as to what other functions I could define.
In XMonad.Hooks.ManageHelpers (https://hackage.haskell.org/package/xmonad-contrib-0.17.0/docs/XMonad-Hooks-ManageHelpers.html), there is ^?, which would be used like below:
className ^? "xxxx" --> doSomething
From my understanding, ^? takes the Query [Char] on the left and the [Char] literal on the right and returns a value type of Query Bool; the value will be True if the [Char] on the left isPrefixOf the [Char] on the right and False otherwise (I think?)
What I would like to create is a new function that is similar, but reversed. Something like,
"xxxx" ?^ className --> doSomething
where ?^ takes the [Char] literal on the left and the Query [Char] on the right and returns a value of type Query Bool; the value should be True if the [Char] on the left isPrefixOf the [Char] on the right and False otherwise.
(In other words, I want to define a new function that checks if some string literal is a prefix of the class name, rather than checking if the class name is a prefix of some string literal.)
Initially, I thought this should be easy, but looking at the source code for ^?, I realized there must be something I am fundamentally missing about my understanding of Haskell.
Here is the definition of ^?:
(^?) :: (Eq a, Functor m) => m [a] -> [a] -> m Bool
q ^? x = fmap (`isPrefixOf` x) q
https://hackage.haskell.org/package/xmonad-contrib-0.17.0/docs/src/XMonad.Hooks.ManageHelpers.html#%5E%3F
What I do not understand is how I would write a function that is a reversed version of this. This definitely won't work:
(?^) :: (Eq a, Functor m) => [a] -> m [a] -> m Bool
x ?^ q = fmap (`isPrefixOf` q) q
yet I do not understand why. What property does Query have that (Query [a]) isPrefixOf ([a]) is acceptable, but not ([a]) isPrefixOf (Query [a])?
Furthermore, how can I go about defining a function with the desired behavior? I am still pretty new to Haskell, so I do not know where to start.
Solution
I was closer than I thought. See the answer for more details, but the solution was just to fix my syntax for the invocation of isPrefixOf (oops):
x ?^ q = fmap (x `isPrefixOf`) q

You gotta switch the arguments to isPrefixOf!
x ?^ q = fmap (x `isPrefixOf`) q
Other spellings are possible, such as this version that doesn't use the infix form of isPrefixOf:
x ^? q = isPrefixOf x <$> q
((<$>) is another name for fmap.)

Related

(Haskell) Can't understand error : No instance for (Ord a) arising from a use of ‘’

I'm trying to code a function that takes a list of string (containing actions to do on the lists inside the tuple) and a tuple of 2 lists of Int as parameters (testReturn).
The function is supposed to execute an action on the Int lists, checks if the first list in the tuple is in ascending order, and then returns a boolean depending on the result.
This code doesn't compile, and I'm not sure about a few things.
My code :
testReturn :: [[Char]] -> ([a], [b]) -> Bool
testReturn [] b = orderedCheck $ fst b
testReturn (a:as) b
| a == "sa" = testReturn as (saFunc $ fst b, snd b)
orderedCheck :: (Ord a) => [a] -> Bool
orderedCheck [] = True
orderedCheck [x] = True
orderedCheck (x:y:xs) = x <= y && orderedCheck (y:xs)
saFunc :: [a] -> [a]
saFunc x
| length x <= 1 = x
saFunc (x:y:xs) = (y:x:xs)
I know that the orderedCheck and saFunc functions work
I'm concerned about :
[[Char]] : Not sure if writing this is right or not, and not sure if it really means a list of strings.
orderedCheck $ fst b : this is the part where I have a GHC error : "No instance for (Ord a) arising from a use of ‘orderedCheck’ ",I looked around and I can't understand what does it mean.
I heard somewhere else that the use of fst and snd may be a bit edgy (is it?), but I don't know how to do without it.
Could you guys please help me understand my errors in order to fix my code?
Thanks!
[[Char]] : Not sure if writing this is right or not, and not sure if it really means a list of strings.
Yes, it does mean a list of strings - that is, the type [String]. This is the same as [[Char]] because in Haskell String and [Char] are type synonyms, literally different ways of referring to the exact same thing. So putting a pair of square brackets round each (to denote a list of that type) also leads to two equivalent types.
String is usually considered more idiomatic than [Char] when writing Haskell code, but it's not a big deal. (Even if you use String everywhere, the compiler might still use [Char] when reporting errors, so it's important to know about this equivalence.)
orderedCheck $ fst b : this is the part where I have a GHC error : "No instance for (Ord a) arising from a use of ‘orderedCheck’ ",I looked around and I can't understand what does it mean.
It's exactly as #Ismor said in the comments - but as I have a little more space in an answer I'll try to give a slightly longer, clearer explanation.
You are calling orderedCheck with the value fst b. And orderedCheck, by your own (correct) type signature, has type (Ord a) => [a] -> Bool. That means its argument must be a list, whose elements are of a type a which satisfies the constraint Ord a.
But you are using it on fst b in testReturn. b is the second argument to the function, which from its type signature must be of type ([a], [b]). This means fst b must be of type [a] - which is a list, so so far so good. But as just mentioned, that type a must have an instance of Ord. And unfortunately we can't guarantee that, because your type signature - [[Char]] -> ([a], [b]) -> Bool - allows both a and b to be absolutely anything. If this code compiled, that type signature would allow me to call that function as, for example, testReturn ["Example"] ([putStrLn "foo"], []) - but putStrLn "foo" has type IO (), which certainly has no Ord instance. (Unless you provide one in your code, which doesn't sound like a great idea - but even if you did, you could easily find another type with no Ord instance which would lead to the same problem.)
The only way to fix this is to fix the type signature of testReturn - it can't actually accept any type as a, because that type must have an Ord instance. So include that requirement, and you'll be fine:
testReturn :: (Ord a) => [[Char]] -> ([a], [b]) -> Bool
(As #MarkSeemann notes, that's exactly the signature GHC would have inferred for you if you'd left out any type signature. I certainly don't recommend leaving off type signatures for top-level functions, but if you're ever not sure of what the signature should be, this technique of leaving it out and then asking GHCi to infer it for you with :t is almost guaranteed to give you what you want.)
I heard somewhere else that the use of fst and snd may be a bit edgy (is it?), but I don't know how to do without it.
I'm not sure what "edgy" means in this context. It's certainly not "wrong", nor is it dangerous in the same way that head and tail are for lists - those functions will crash (at runtime) when given an empty list, whereas fst and snd will work fine for any 2-tuple (and if given a value that's not a 2-tuple, your code will fail to compile - so there is zero risk of a runtime crash).
However, it's not very elegant compared to pattern-matching, which here is rather like "destructuring" in other languages. I think most Haskellers would write your function like this instead, which is equivalent to your code and hopefully self-explanatory:
testReturn [] (b, _) = orderedCheck b
testReturn (a:as) (b, c)
| a == "sa" = testReturn as (saFunc b, c)
(Note that this function appears incomplete, and will crash if called with a non-empty first argument whose first element is anything other than "sa".)

Apply `a -> Maybe b` function to `Maybe a`

Say I have a function parse :: String -> Maybe (Integer, String) that parses the first integer i from a list of integers encoded as a string s like 1,2,3 and returns Just (i, s') where s' is the remaining string or Nothing if parsing failed.
How can I then concisely apply this function to a Maybe String? parse <$> maybeString has redundant type Maybe (Maybe (Integer, String)) and writing a custom pattern matching function for this seems to be overkill.
More generally: is there an equivalent to <$> of type (a -> f b) -> f a -> f b (or would that not make sense?).
EDIT: I'm stupid, I just realized there's Hoogle for this. Is this what we need Monads for? (I haven't reached that part of Haskell yet).
Sounds like you're looking for (>>=) which you can use like maybeString >>= parse. This requires the data type you're working with to be a Monad which Maybe satisfies.

Define a haskell function [IO a] -> IO[a]

I am doing a haskell exercise, regarding define a function accumulate :: [IO a] -> IO [a]
which performs a sequence of interactions and accumulates their result in a list.
What makes me confused is how to express a list of IO a ? (action:actions)??
how to write recursive codes using IO??
This is my code, but these exists some problem...
accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do
value <- action
list <- accumulate (action:actions)
return (convert_to_list value list)
convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
What you are trying to implement is sequence from Control.Monad.
Just to let you find the answer instead of giving it, try searching for [IO a] -> IO [a] on hoogle (there's a Source link on the right hand side of the page when you've chosen a function).
Try to see in your code what happens when list of actions is empty list and see what does sequence do to take care of that.
There is already such function in Control.Monad and it called sequence (no you shouldn't look at it). You should denote the important decision taken during naming of it. Technically [IO a] says nothing about in which order those Monads should be attached to each other, but name sequence puts a meaning of sequential attaching.
As for the solving you problem. I'd suggest to look more at types and took advice of #sacundim. In GHCi (interpreter from Glasgow Haskell Compiler) there is pretty nice way to check type and thus understand expression (:t (:) will return (:) :: a -> [a] -> [a] which should remind you one of you own function but with less restrictive types).
First of all I'd try to see at what you have showed with more simple example.
data MyWrap a = MyWrap a
accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
MyWrap value = action -- use the pattern matching to unwrap value from action
-- other variant is:
-- value = case action of
-- MyWrap x -> x
MyWrap values = accumulate (action:actions)
I've made the same mistake that you did on purpose but with small difference (values is a hint). As you probably already have been told you could try to interpret any of you program by trying to inline appropriate functions definitions. I.e. match definitions on the left side of equality sign (=) and replace it with its right side. In your case you have infinite cycle. Try to solve it on this sample or your and I think you'll understand (btw your problem might be just a typo).
Update: Don't be scary when your program will fall in runtime with message about pattern match. Just think of case when you call your function as accumulate []
Possibly you looking for sequence function that maps [m a] -> m [a]?
So the short version of the answer to your question is, there's (almost) nothing wrong with your code.
First of all, it typechecks:
Prelude> let accumulate (action:actions) = do { value <- action ;
list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]
Why did I use return (value:list) there? Look at your second function, it's just (:). Calling g
g a [] = a:[]
g a xs = a:xs
is the same as calling (:) with the same arguments. This is what's known as "eta reduction": (\x-> g x) === g (read === as "is equivalent").
So now just one problem remains with your code. You've already taken a value value <- action out of the action, so why do you reuse that action in list <- accumulate (action:actions)? Do you really have to? Right now you have, e.g.,
accumulate [a,b,c] ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....
One simple fix and you're there.

what is [a] as a type in Haskell?

This question is about type in Haskell programming language.
When I type
:t []
I get the return as:
[] :: [a]
What is [a]?
Rewriting it like so might make things clearer:
[] :: forall a. [a]
So, since it doesn't contain any value, haskell can't decide on a type and leaves it open. If you use it in a typed expression, however, like
x = []
f :: [Int] -> [Int]
f l = l
y = f x
it automatically gets resolved to [Int], since it is used as this type.
It's a placeholder. It basically means any type could go there. In other words, if you had a function
someFunc :: [Int] -> ()
You could pass [] to it because [] is [a], which will match [Int] (by replacing the a placeholder with the concrete Int type).
Now if you look at, say, id, you'll find it has the type a -> a. This means that it's a function that takes an object of any type, and returns an object of the same type. Interestingly, because the function knows absolutely nothing about the object it's given (since it has no constraints on the type), you know that this function has to do either of two things:
Return the input object, or
Return ⊥ (bottom).

Create a list using do syntax?

I'm relatively new to Haskell. I'm creating a small api/dsl on top of happstack-lite, which will have an interface more similar to Sinatra, mostly to learn. As a part of this, I want to construct an array using do syntax (basically because it would be prettier than the msum [route, route, route] thing. The usage of the monad would look something like this:
someFunctionThatMakesStrings :: String
unwrapMyMonadAndGiveMeAList :: MyMonad _ -> [String]
makeAList :: [String]
makeAList = unwrapMyMonadAndGiveMeAList do
someFunctionThatMakesStrings
someFunctionThatMakesStrings
someFunctionThatMakesStrings
...
So makeAList would return a list with 3 strings. Notice that I would like to use functions inside it that aren't aware of the monad (they just return a string).
I can do this with Writer, but each function called has to be aware of the Writer monad, and it also seems like overkill (I don't need the return type tuple, and the way I got it to work involved lots of wrapping/unwrapping)
I tried using the list monad itself, but it clearly is intended for something different than this.
So which of my assumptions need to change, and then how would I make a new list-construction monad from scratch? How close can I get?
Writer is definitely what you want here; you can avoid "exposing" Writer to the outside at the cost of a little more overhead in the definitions themselves:
foo :: [String]
foo = execWriter $ do
tell otherList1
tell otherList2
tell otherList3
otherList1 :: [String]
otherList1 = execWriter $ do
...
i.e., you can keep the use of Writer local to each definition, but you have to wrap each list you want to use as a "source" in tell. The key thing here is to use execWriter, which discards the result element of the tuple (it's identical to snd . runWriter).
However, if you have a lot of definitions like this, I would recommend simply using Writer directly, and only applying execWriter in the place where you want the combined result; you can make the types a bit cleaner by defining a synonym like type Foo = Writer [String].
I'm not sure what advantage constructing your own list-creation monad would be; it would end up being identical to Writer [String].
The list monad is indeed irrelevant to what you want to do here.
As far as defining your own list-writing monad goes, it's pretty simple:
data ListWriter a = ListWriter a [String]
runListWriter :: ListWriter a -> (a, [String])
runListWriter (ListWriter a xs) = (a, xs)
execListWriter :: ListWriter a -> [String]
execListWriter = snd . runListWriter
instance Monad ListWriter where
return a = ListWriter a []
ListWriter a xs >>= f = ListWriter b (xs ++ ys)
where ListWriter b ys = f a
The only tricky part is (>>=), where we have to take only the value part of the left argument, feed it into the right hand argument, take it apart, and then combine the two lists inside, wrapping it back up with the result of the right hand side.

Resources