Function from Data.Map -> Maybe as a class instance. Confused about how to implement - haskell

As I was working through cis 194 (week 5) I came across a problem that introduced two new concepts to me at once, and I'm having difficulty making it, at the very least, output the correct type.
My goal is to implement var in the instance declared at the bottom, however, I have never used an instance that was a function before, and nor have I used Data.Map, so I'm not very clear on what my solution syntax should even look like.
{-# LANGUAGE FlexibleInstances #-}
import qualified Data.Map as M
class HasVars a where
var :: String -> a
-- | This instance allows variables to be interpreted as functions from a
-- mapping of variables to Integer values to (possibly) Integer values
instance HasVars (M.Map String Integer -> Maybe Integer) where
-- not sure how to implement var here

So when you have
class HasVars a where
var :: String -> a
That means that, for any instance a, you have a function var :: String -> a.
So, if Map String Integer -> Maybe Integer is an instance, then that means that you have to provide a function:
var :: String -> (Map String Integer -> Maybe Integer)
Remember that (->) associates from the right, so the parentheses here are optional --
var :: String -> Map String Integer -> Maybe Integer
So, var is a function that takes a String and a Map and returns a Maybe Integer. Let's write it!
instance HasVars (Map String Integer -> Maybe Integer) where
-- var :: String -> Map String Integer -> Maybe Integer
var str mp = M.lookup str mp
And this works!
edit: Question in answer
I see that you're wondering why
var str = M.lookup str
works. Remember that M.lookup str doesn't return a Maybe Integer. It returns a Map String Integer -> Maybe Integer. Which is exactly what a should be...exactly what you want. var str is now a function that takes a map and returns a Maybe Integer.
M.lookup str doesn't have a map, yes, so it can't return a Maybe Integer. But it's a Map String Integer -> Maybe Integer. So var "hello" is now a Map String Integer -> Maybe Integer. var "hello" gives you a function that takes a map and returns a Maybe Integer. So if you give var "hello" a map, like var "hello" mp, then you get a Maybe Integer :D

So, I've come up with something that at the very least compiles. I had unnecessarily caused myself some confusion when I was attempting to solve this by repeatedly using Maybe as a constructor, and staring blankly at the error message that it wasn't defined. Just is the constructor for Maybe, Maybe isn't a constructor; too many times...
Secondly, I completely blanked by using lookup ... instead of M.lookup ..., leading to unexpected type results.
Those stumblings aside, here's what I tried
instance HasVars (M.Map String Integer -> Maybe Integer) where
var str = M.lookup str -- can be Eta-reduced
This compiles, but what doesn't make too much sense to me is that per the instance declaration, shouldn't I be providing a key-value Map? M.lookup will give back a Maybe Integer, but it just doesn't seem like I've given it enough to do that, because it needs a key and a Map, and I don't seem to have a Map. Perhaps my understanding of how class instances work is off.

Related

Passing any type in function signature in Haskell

I want to pass a function a wildcard or any type or even a way to choose between either of multiple types rather than just restrict it to String, or Number, or Boolean, for example:
myFunction :: a -> String
or
myFunction :: _ -> String
or
myFunction :: (String || Number) -> String
Is that possible?
myFunction :: a -> String is technically possible, however it's profoundly useless – since this must be able to deal with an argument of any type, there's nothing you can actually do with the argument. (It's a bit like getting a can with a completely unspecified substance – you wouldn't eat it in case it's corrosive, you couldn't use it for cleaning purposes in case it's fat, paint or glue, you couldn't process it further... in case of an unrestricted Haskell type you couldn't even analyse it.)
If you narrow it down to types that support some kind of common operation, a polymorphic argument can make sense:
myFunction' :: Show a => a -> String
myFunction' x = "The value is " ++ show x
Your other approach, supporting only two very specific types, is also possible:
myFunction'' :: Either String Integer -> String
myFunction'' (Left s) = "Got a string: “" ++ s ++ "”"
myFunction'' (Right n) = "Got a number: " ++ show n
Note that these two approaches are quite different: Show a => a -> String can be used as String -> String or as Integer -> String, or in fact any other type which supports the show operation (including newly-defined types of your own), but you must decide at compile-time which type you want. At runtime, all arguments passed to this function must then have the same type.
Either String Integer -> String can accept a mixture of String- and Integer values at runtime, but is always restricted to only these two types.
Defining a function a -> String is easily possible, it just won't be able to do anything useful unless you also restrict a to some typeclass (like Show).
_ -> String is not valid syntax. If it were, I imagine it would do the same as a -> String, so you can just use that.
(String || Number) -> String is also not valid syntax, but Either String Number -> String is. You can also define your data type with constructors for the types you want to allow.
myFunction :: a -> String means that myFunction can take an argument of any type, but will always return a string. This is legal Haskell syntax.
With PartialTypeSignatures enabled, myFunction :: _ -> String is legal Haskell syntax, with _ acting as a "hole", or a way to get the compiler to tell you what type it inferred at that position:
Temp.hs:4:15: warning: [-Wpartial-type-signatures]
• Found type wildcard ‘_’ standing for ‘String’
• In the type signature: myFunction :: _ -> String
|
4 | myFunction :: _ -> String
| ^
If you enable TypeOperators, then you can define type (||) = Either, which make myFuncion :: (String || Number) -> String mean that myFuncion is a function that takes an argument of type Either String Number and returns a String:
type Number = Integer
type (||) = Either
myFuncion = (String || Number) -> String
myFuncion (Left string) = string
myFuncion (Right number) = show number

New type declaring functions?

I'm familiar with the newtype declaration:
newtype MyAge = Age {age :: Int} deriving (Show, Eq, Ord)
In this instance Age is an Int, however I've come across the code below and I can't understand it:
newtype Ages a = Ages {age :: String -> [(a,String)]}
This appears to be a function declaration? (takes string, returns list of tuples containing 'a' and string) - is this correct?
N.B I've just realized this is just basic record syntax to declare a function.
Additionally, I've tried to implement this type, but I must be doing something wrong:
newtype Example a = Example {ex :: Int -> Int}
myexample = Example {ex = (\x -> x + 1)}
This compiles, however I don't understand why as I haven't passed the 'a' parameter?
This appears to be a function declaration?
Yes. Specifically, String -> [(a,String)] is a function type. A newtype declaration is analogous to a simple wrapper around any given type. There's no restriction that says you can't make it based on a function type, and it works in exactly the same way.
Also remember that you can always replace newtype with data; in this case, thinking about the resulting type as a record type that has a field that is a function might be helpful; newtype is just a special, optimized case.
One other thing to mention is that your two lines also differ in that the second one is parametrized over a. This can of course be used with regular types:
newtype MyWrapper a = MyWrapper a
or a function type can be newtype-d without parametrisation
newtype MyFunction = MyFunction (Float -> Float)
You can also write the above using the record syntax that gives you the "getter" function as well.

converting a list of string into a list of tuples in Haskell

I have a list of strings:
[" ix = index"," ctr = counter"," tbl = table"]
and I want to create a tuple from it like:
[("ix","index"),("ctr","counter"),("tbl","table")]
I even tried:
genTuple [] = []
genTuples (a:as)= do
i<-splitOn '=' a
genTuples as
return i
Any help would be appriciated
Thank you.
Haskell's type system is really expressive, so I suggest to think about the problem in terms of types. The advantage of this is that you can solve the problem 'top-down' and the whole program can be typechecked as you go, so you can catch all kinds of errors early on. The general approach is to incrementally divide the problem into smaller functions, each of which remaining undefined initially but with some plausible type.
What you want is a function (let's call it convert) which take a list of strings and generates a list of tuples, i.e.
convert :: [String] -> [(String, String)]
convert = undefined
It's clear that each string in the input list will need to be parsed into a 2-tuple of strings. However, it's possible that the parsing can fail - the sheer type String makes no guarantees that your input string is well formed. So your parse function maybe returns a tuple. We get:
parse :: String -> Maybe (String, String)
parse = undefined
We can immediately plug this into our convert function using mapMaybe:
convert :: [String] -> [(String, String)]
convert list = mapMaybe parse list
So far, so good - but parse is literally still undefined. Let's say that it should first verify that the input string is 'valid', and if it is - it splits it. So we'll need
valid :: String -> Bool
valid = undefined
split :: String -> (String, String)
split = undefined
Now we can define parse:
parse :: String -> Maybe (String, String)
parse s | valid s = Just (split s)
| otherwise = Nothing
What makes a string valid? Let's say it has to contain a = sign:
valid :: String -> Bool
valid s = '=' `elem` s
For splitting, we'll take all the characters up to the first = for the first tuple element, and the rest for the second. However, you probably want to trim leading/trailing whitespace as well, so we'll need another function. For now, let's make it a no-op
trim :: String -> String
trim = id
Using this, we can finally define
split :: String -> (String, String)
split s = (trim a, trim (tail b))
where
(a, b) = span (/= '=') s
Note that we can safely call tail here because we know that b is never empty because there's always a separator (that's what valid verified). Type-wise, it would've been nice to express this guarantee using a "non-empty string" but that may be a bit overengineered. :-)
Now, there are a lot of solutions to the problem, this is just one example (and there are ways to shorten the code using eta reduction or existing libraries). The main point I'm trying to get across is that Haskell's type system allows you to approach the problem in a way which is directed by types, which means the compiler helps you fleshing out a solution from the very beginning.
You can do it like this:
import Control.Monda
import Data.List
import Data.List.Split
map ((\[a,b] -> (a,b)) . splitOn "=" . filter (/=' ')) [" ix = index"," ctr = counter"," tbl = table"]

How can I have a function in haskell return either a boolean or a list of booleans?

I have function in haskell (lets call it 'dumb') which calls 3 different functions. These three different functions return different types, for example, a boolean or a list of booleans. How can I define function 'dumb' to either return a boolean or a list of booleans?
data Sumtype = givelist Integer | getprod Integer
prod :: Int -> Int
prod x = x*3
listnums :: Int -> [Int]
listnums x = [1...x]
dumb :: Sumtype -> (what comes here..?)
dumb (givelist x) -> listnums x
dum (getprod x) -> prod x
You make it return Either Boolean [Boolean]. But I'm suspicious about your motives. It sounds like an X/Y problem.
You're probably looking for the the Either type, although with it your function will return Either values. It's defined like this:
data Either a b = Left a | Right b
When you want to define a function that can return either a Bool or a list of Bools its type should look something like this:
dumb :: Either Bool [Bool]
In this case 'dumb' will be a function that doesn't take any arguments and return either a Bool or a list of Bools. In the function's body you can return a Bool like this:
Left bool
Or a list of bools like this:
Right [bool]
You can see a concrete example here: http://en.wikibooks.org/wiki/Haskell/More_on_datatypes#More_than_one_type_parameter
All that said though, the reason Sebastian asked you for more details is that Either is rarely used outside of error handling (AFAIK I know anyway). It's possible that in your case you don't really need it at all, but we can't be sure unless you tell us more about the other functions you use in 'dumb' and about your goals.
Unrelated Probems
It appears you are a beginner - welcome to Haskell! I strongly suggest you read and work through one of the many tutorials as that is more efficient and complete than asking individual questions.
Syntax
Let's start with correcting the syntax errors. Constructors, such as Givelist and Getprod must start with a capital letter. The function dumb was typo'ed once. Function definitions use = and not ->.
Types
Now we have type errors to address. The Sumtype uses Integer and you then switch to using Int. Lets just stick with Integer for simplicity.
With these fixes we get:
data Sumtype = Givelist Integer | Getprod Integer
prod :: Integer -> Integer
prod x = x*3
listnums :: Integer -> [Integer]
listnums x = [1...x]
dumb :: Sumtype -> (what comes here..?)
dumb (Givelist x) = listnums x
dumb (Getprod x) = prod x
The Question
You want to know "what comes here" where 'here' is the result type. As written, the function is actually invalid. One definition yields a list of integers, [Integer], while the other yields a single integer Integer. One solution is to use a sum type such as Either Integer [Integer] - this is very much like your pre-existing Sumtype:
dumb :: Sumtype -> Either Integer [Integer]
So now we need to return a constructor of Either in our function definitions. You can lookup the documentation or use :info Either in GHCi to learn the constructors if you don't have them memorized.
dumb (Givelist x) = Right (listnums x)
dumb (Getprod x) = Left (prod x)
Notice we had to use Left for the second case which returns an Integer, because the first type we wrote after Either (the left type) is Integer.

Differentiate between String and [Char]

I know that String is defined as [Char], yet I would like to make a difference between the two of them in a class instance. Is that possible with some clever trick other than using newtype to create a separate type? I would like to do something like:
class Something a where
doSomething :: a -> a
instance Something String where
doSomething = id
instance (Something a) => Something [a] where
doSomething = doSoemthingElse
And get different results when I call it with doSomething ("a" :: [Char]) and doSomething ("a" :: String).
I do know about FlexibleInstances and OverlappingInstances but they obviously don't cut the case.
That is not possible. String and [Char] are the same type. There is no way to distinguish between the two types. With OverlappingInstances you can create separate instances for String and [a], but [Char] will always use the instance for String.
Why don't you define functions for each case:
doSomethingString :: String -> String
doSomethingString = id
doSomethingChars :: (Char -> Char) -> String -> String
doSomethingChars f = ...
As said before, String and [Char] IS effectively the same.
What you can do though is defining a newtype. It wraps a type (at no-cost as it is completely removed when compiled) and makes it behave like a different type.
newtype Blah = Blah String
instance Monoid Blah where
mempty = Blah ""
mappend (Blah a) (Blah b) = Blah $ a ++ "|" ++ b

Resources