Here is the code:
import qualified View.TreeWidget as TreeWidget
main :: IO ()
main = do
print $ bla "sdfsd"
bla someString = case someString of
TreeWidget.name -> True
"sdfsd" -> False
_ -> True
TreeWidget.name
is a function defined in a file TreeWidget.hs
like this:
name :: String
name = "tree_list_name"
Here is the error:
src/View/Main.hs:8:3: error:
Qualified name in binding position: TreeWidget.name
|
8 | TreeWidget.name -> True
| ^^^^^^^^^^^^^^^
- Why is this happening?
- What can be done?
Thanks.
CodePudding user response:
When you see a lower case pattern, that means a variable which matches everything. You might as well use a pattern wildcard (_
) if the variable is not used on the right-hand side.
name -> True
A pattern variable functions as a binder, you cannot substitute a pattern like "tree_list_name" -> ..
with
name -> ..
name :: String
name = "tree_list_name"
It also means you can't reference a pattern variable from some other module, which is what TreeWidget.name
is doing.
The solution is to use pattern synonyms. In the View.TreeWidget
module write something like
{-# Language PatternSynonyms #-}
module View.TreeWidget (pattern Name) where
pattern Name :: String
pattern Name = "tree_list_name"
Now you can use Name
both as an expression and a pattern. So you can now write
import qualified View.TreeWidget as TreeWidget
bla :: String -> Bool
bla TreeWidget.Name = True
bla "sdfsd" = False
bla _ = True
CodePudding user response:
As Iceland_jack explained, you can't use values like name
as patterns. What you can use as patterns is essentially constructors and literals, where constructors are normally the uppercase things appearing in a data
declaration like Just
and Nothing
in the Maybe
type. The PatternSynonyms
extension allows defining custom constructors for already declared types.
However, although I generally favour patterns over equality check, this seems to be a case where it would make more sense to just check whether someString == TreeWidget.name
and act accordingly. This can easily be done with guards:
bla someString
| someString==TreeWidget.name = True
bla "sdfsd" = False
bla _ = True
Of course, since the result is again a boolean you could also just use logical operators:
bla someString = someString==TreeWidget.name || someString/="sdfsd"
If you have a taste for point-freeness, this can also be written
bla = or . ([(==TreeWidget.name), (/="sdfsd")]<*>) . pure
... but more effective would be to just use a shorter name for someString
.