How can I parse a string to a function in Haskell? - haskell

I want a function that looks something like this
readFunc :: String -> (Float -> Float)
which operates something like this
>(readFunc "sin") (pi/2)
>1.0
>(readFunc "(+2)") 3.0
>5.0
>(readFunc "(\x -> if x > 5.0 then 5.0 else x)") 2.0
>2.0
>(readFunc "(\x -> if x > 5.0 then 5.0 else x)") 7.0
>5.0
The incredibly naive approach (note this must be compiled with {-# LANGUAGE FlexibleContexts #-})
readFunc :: (Read (Float -> Float)) => String -> (Float -> Float)
readFunc s = read s
gives
No instance for (Read (Float -> Float)) ...
Which makes sense since no such instance exists. I understand that I can parse the input string character by character by writing a map from String to Float -> Float but I want to be able to parse at least the most common functions from prelude, and even that would be way more work than I want to commit to. Is there an easy way of doing this?
Just one solution using hint
import Language.Haskell.Interpreter hiding (typeOf)
import Data.Typeable (typeOf)
data Domain = Dom Float Float Float Float Domain
| SDom Float Float Float Float
deriving (Show, Read)
--gets all the points that will appear in the domain
points (SDom a b c d) m = [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]]
points (Dom a b c d next) m = points next m ++ [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]]
readFunc = do
putStrLn "Enter a domain (as Dom x-min x-max y-min y-max subdomain, or, SDom x-min x-max y-min y-max)"
domain' <- getLine
let domain = (read domain') :: Domain
--
putStrLn "Enter a mesh size"
meshSize' <- getLine
let meshSize = (read meshSize') :: Float
--
putStrLn "Enter an initial value function (as f(x,y))"
func' <- getLine
values' <- runInterpreter $ setImports["Prelude"] >>
eval ("map (\\(x,y) -> " ++ func' ++ ")" ++ show (points domain meshSize))
let values = (\(Right v) -> (read v)::([Float])) values'
--the haskell expression being evaluated
putStrLn $ ("map (\\(x,y) -> " ++ func' ++ ")" ++ show (points domain meshSize))
--prints the actual values
putStrLn $ show values
--the type is indeed [float]
putStrLn $ show $ typeOf values

You can use the hint package, or plugins. I'll show you the former (partly because my Windows installation is clearly a little broken in that cabal doesn't share my belief that I have C installed, so cabal install plugins fails).
String -> Function is easy:
import Language.Haskell.Interpreter
getF :: String -> IO (Either InterpreterError (Float -> Float))
getF xs = runInterpreter $ do
setImports ["Prelude"]
interpret xs (as :: Float -> Float)
You may want to add additional modules to the imports list. This tests out as
ghci> getF "sin" >>= \(Right f) -> print $ f (3.1415927/2)
1.0
ghci> getF "(\\x -> if x > 5.0 then 5.0 else x)" >>= \(Right f) -> print $ f 7
5.0
(Notice the escaping of the escape character \.)
Error messages
As you may have noticed, the result is wrapped in the Either data type. Right f is correct output, whereas Left err gives an InterpreterError message, which is quite helpful:
ghci> getF "sinhh" >>= \(Left err) -> print err
WontCompile [GhcError {errMsg = "Not in scope: `sinhh'\nPerhaps you meant `sinh' (imported from Prelude)"}]
Example toy program
Of course, you can use either with your code to deal with this. Let's make a fake example respond. Your real one will contain all the maths of your program.
respond :: (Float -> Float) -> IO ()
respond f = do
-- insert cunning numerical method instead of
let result = f 5
print result
A simple, one-try, unhelpful version of your program could then be
main =
putStrLn "Enter your function please:"
>> getLine
>>= getF
>>= either print respond
Example sessions
ghci> main
Enter your function please:
\x -> x^2 + 4
29.0
ghci> main
Enter your function please:
ln
WontCompile [GhcError {errMsg = "Not in scope: `ln'"}]
It does type checking for you:
ghci> main
Enter your function please:
(:"yo")
WontCompile [GhcError {errMsg = "Couldn't match expected type `GHC.Types.Float'\n with actual type `GHC.Types.Char'"}]

Related

How can I get output mention in below

readInts = fmap (map read.words) getLine
readInts :: IO [Int]
main = do
putStrLn "List number of A: "
num1 <- readInts
let a = [] ++ num1
putStrLn "List number of B: "
num2 <- readInts
let b = [] ++ num2
Choose some element a of A and some element b of B such that a + b doesn't belong to A and doesn't belong to B
Serious
If your instructor isn't teaching, and that isn't just you being burned out and stressed, then talk to the instructor. They probably aren't trying to waste your and their time. If that doesn't work then talk to the professor.
As for getting homework help here, it is entirely doable but help is very unlikely to appear without some semblance of an attempt and a clear cut issue. You usually need to come to the table with how the problem can be solved and have problems translating that how into the specifics of Haskell or whatever target language.
Cheeky
A cheeky response I'd use if I were in the classroom:
This is a finite domain so I'd just use DPLL. DPLL is a general purpose algorithm for finite domains that allows us to just state the problem as a symbolic computation and constraints then request satisfying models. We'll construct the problem first then use the SBV library to get the model.
Choose some element a of A
So lets define the set A (called as) as a list of symbolics and then constrain an existential to being a member of this set!
a <- exists "value1"
constrain (a `sElem` as)
and some element b of B
OK, same thing. We make a list of symbolic values and constrain an existential to being a member.
b <- exists "value2"
constrain (b `sElem` bs)
such that a + b
Let's define an alias for this:
let c = a + b
doesn't belong to A
We can just reuse the test for membership, sElem, and symbolic negation sNot.
constrain $ sNot (c `sElem` as)
and doesn't belong to B
Yep, same!
constrain $ sNot (c `sElem` bs)
Putting it together
Honestly the hardest part is actually running your problem more than stating it. We need to read the inputs (as you showed), call the solver (sat), and get the answer (aka the "model) via extractModel which can finally be printed.
#!/usr/bin/env cabal
{- cabal:
build-depends:
base, sbv >= 8.4
-}
{-# LANGUAGE ViewPatterns #-}
import Data.SBV
readInts :: IO [Int64]
readInts = fmap read . words <$> getLine
readInt :: IO Int64
readInt = read <$> getLine
main =
do putStrLn "List number of A: "
a <- readInts
putStrLn "List number of B: "
b <- readInts
result <- getValues a b
let values :: Maybe (Int64,Int64)
values = extractModel result
print values
getValues :: [Int64] -> [Int64] -> IO SatResult
getValues (map literal -> as) (map literal -> bs) = sat $
do a <- exists "value1"
constrain (a `sElem` as)
b <- exists "value2"
constrain (b `sElem` bs)
let c = a + b
constrain $ sNot (c `sElem` as)
constrain $ sNot (c `sElem` bs)
Because this uses SBV you'll have to have first installed z3. I included a cabal header to auto build as a package. For example:
brew install z3
...
chmod +x mycode.hs
./mycode.hs
...
List number of A:
1 3 4 5
List number of B:
1 2 3
Just (3,3)

What is the difference between `readMay` and `readMaybe`?

The two functions readMay and readMaybe have the same signature Read a => String -> Maybe a.
Is there any difference between them? If so, what are they? Which of the two function should be preferred?
There is no difference. Here's how readMay's defined:
-- | This function provides a more precise error message than 'readEither' from 'base'.
readEitherSafe :: Read a => String -> Either String a
readEitherSafe s = case [x | (x,t) <- reads s, ("","") <- lex t] of
[x] -> Right x
[] -> Left $ "no parse on " ++ prefix
_ -> Left $ "ambiguous parse on " ++ prefix
where
maxLength = 15
prefix = '\"' : a ++ if length s <= maxLength then b ++ "\"" else "...\""
where (a,b) = splitAt (maxLength - 3) s
readMay :: Read a => String -> Maybe a
readMay = eitherToMaybe . readEitherSafe
And here is readMaybe:
-- | Parse a string using the 'Read' instance.
-- Succeeds if there is exactly one valid result.
-- A 'Left' value indicates a parse error.
--
-- #since 4.6.0.0
readEither :: Read a => String -> Either String a
readEither s =
case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
[x] -> Right x
[] -> Left "Prelude.read: no parse"
_ -> Left "Prelude.read: ambiguous parse"
where
read' =
do x <- readPrec
lift P.skipSpaces
return x
-- | Parse a string using the 'Read' instance.
-- Succeeds if there is exactly one valid result.
--
-- #since 4.6.0.0
readMaybe :: Read a => String -> Maybe a
readMaybe s = case readEither s of
Left _ -> Nothing
Right a -> Just a
They differ in the intermediate error message (readEitherSafe shows the input), but the result will be same.
readMay from Safe predates readMaybe from Text.Read. Unless you're on a base version less than 4.6.0.0, use readMaybe from Text.Read as it does not need another package.

Is this syntax as expressive as the do-notation?

The do notation allows us to express monadic code without overwhelming nestings, so that
main = getLine >>= \ a ->
getLine >>= \ b ->
putStrLn (a ++ b)
can be expressed as
main = do
a <- getLine
b <- getLine
putStrLn (a ++ b)
Suppose, though, the syntax allows ... #expression ... to stand for do { x <- expression; return (... x ...) }. For example, foo = f a #(b 1) c would be desugared as: foo = do { x <- b 1; return (f a x c) }. The code above could, then, be expressed as:
main = let a = #getLine in
let b = #getLine in
putStrLn (a ++ b)
Which would be desugared as:
main = do
x <- getLine
let a = x in
return (do
x' <- getLine
let b = x' in
return (putStrLn (a ++ b)))
That is equivalent. This syntax is appealing to me because it seems to offer the same functionality as the do-notation, while also allowing some shorter expressions such as:
main = putStrLn (#(getLine) ++ #(getLine))
So, I wonder if there is anything defective with this proposed syntax, or if it is indeed complete and equivalent to the do-notation.
putStrLn is already String -> IO (), so your desugaring ... return (... return (putStrLn (a ++ b))) ends up having type IO (IO (IO ())), which is likely not what you wanted: running this program won't print anything!
Speaking more generally, your notation can't express any do-block which doesn't end in return. [See Derek Elkins' comment.]
I don't believe your notation can express join, which can be expressed with do without any additional functions:
join :: Monad m => m (m a) -> m a
join mx = do { x <- mx; x }
However, you can express fmap constrained to Monad:
fmap' :: Monad m => (a -> b) -> m a -> m b
fmap' f mx = f #mx
and >>= (and thus everything else) can be expressed using fmap' and join. So adding join would make your notation complete, but still not convenient in many cases, because you end up needing a lot of joins.
However, if you drop return from the translation, you get something quite similar to Idris' bang notation:
In many cases, using do-notation can make programs unnecessarily verbose, particularly in cases such as m_add above where the value bound is used once, immediately. In these cases, we can use a shorthand version, as follows:
m_add : Maybe Int -> Maybe Int -> Maybe Int
m_add x y = pure (!x + !y)
The notation !expr means that the expression expr should be evaluated and then implicitly bound. Conceptually, we can think of ! as being a prefix function with the following type:
(!) : m a -> a
Note, however, that it is not really a function, merely syntax! In practice, a subexpression !expr will lift expr as high as possible within its current scope, bind it to a fresh name x, and replace !expr with x. Expressions are lifted depth first, left to right. In practice, !-notation allows us to program in a more direct style, while still giving a notational clue as to which expressions are monadic.
For example, the expression:
let y = 42 in f !(g !(print y) !x)
is lifted to:
let y = 42 in do y' <- print y
x' <- x
g' <- g y' x'
f g'
Adding it to GHC was discussed, but rejected (so far). Unfortunately, I can't find the threads discussing it.
How about this:
do a <- something
b <- somethingElse a
somethingFinal a b

Showing the name of a function [duplicate]

Is it possible in Haskell to implement a function which returns its own function name?
A possible type could be (a -> b) -> String.
You want a function that takes a function argument, and returns the definition site variable name that corresponds to the name of that function?
This isn't possibly without meta-programming, which is usually a sign you're doing something wrong :).
But assuming you're not, one way to achieve something in the right direction is via Template Haskell, which can get at unique names (how the compiler names things). E.g.
Prelude Language.Haskell.TH> :set -XTemplateHaskell
Prelude Language.Haskell.TH> let f x y = x + y
Prelude Language.Haskell.TH> $( stringE . show =<< reify 'f )
"VarI f_1627394057
(ForallT [PlainTV a_1627394063]
[ClassP GHC.Num.Num [VarT a_1627394063]]
(AppT (AppT ArrowT (VarT a_1627394063))
(AppT (AppT ArrowT (VarT a_1627394063))
(VarT a_1627394063))))
Nothing (Fixity 9 InfixL)"
And now we know a lot about the variable. So you can play games by passing a Name to the function (via 'f) rather than f itself.
You are certainly in the world of reflection and meta-programming though, so it would help to know more about what you are trying to do.
To clarify something mentioned in dons' post: no functions have names in Haskell. There are bindings which may bind functions, but if I had such a function (call it getName) as you seek then what would you expect this to return:
let f x = x
g = f
h = f
in getName g == getName h
I don't know what you need it for, but maybe a simplistic solution suffices? Like so:
data NamedFunction a b = NamedFunction {
name :: String,
apply :: a -> b
}
timesTwo :: NamedFunction Int Int
timesTwo = NamedFunction "timesTwo" (\x -> 2 * x)
which you can use as follows:
ghci> timesTwo `apply` 7
14
ghci> name timesTwo
"timesTwo"
You can then write your own version of (.):
-- contrast (.) :: (b -> c) -> (a -> b) -> (a -> c)
compose :: NamedFunction b c -> NamedFunction a b -> NamedFunction a c
compose (NamedFunction n1 f1) (NamedFunction n2 f2) =
NamedFunction (n1++ " . " ++ n2) (f1 . f2)
In ghci:
ghci> let f = timesTwo `compose` timesTwo in (f `apply` 7, name f)
(28,"timesTwo . timesTwo")
You'll have to reimplement your own versions of map, filter and so on, and you're bound to run into other problems later, but maybe this is all you need...
Am I missing something? This function returns its own function name.
Prelude> let myNameIs::(a->b) -> String; myNameIs f = "myNameIs"
Prelude> :type myNameIs
myNameIs :: (a -> b) -> String
Prelude> myNameIs myNameIs
"myNameIs"
You can preprocess your source code with CPP. In CPP
#define _NAMEOF(name) #name
defines a macro, _NAMEOF, for stringifying text (including surrounding it with programmer's quotation marks). You can then use it as follows:
head [] = error $ _NAMEOF(head) ++ ": empty list!"
which CPP should translate into a valid Haskell source code line:
head [] = error $ "head" ++ ": empty list!"

Non-exhaustive patterns in lambda

I am getting Non-exhaustive patterns in lambda. I am not sure of the cause yet. Please anyone how to fix it. The code is below:
import Control.Monad
import Data.List
time_spent h1 h2 = max (abs (fst h1 - fst h2)) (abs (snd h1 - snd h2))
meeting_point xs = foldl' (find_min_time) maxBound xs
where
time_to_point p = foldl' (\tacc p' -> tacc + (time_spent p p')) 0 xs
find_min_time min_time p = let x = time_to_point p in if x < min_time then x else min_time
main = do
n <- readLn :: IO Int
points <- fmap (map (\[x,y] -> (x,y)) . map (map (read :: String->Int)) . map words . lines) getContents
putStrLn $ show $ meeting_point points
This is the lambda with the non-exhaustive patterns: \[x,y] -> (x,y).
The non-exhaustive pattern is because the argument you've specified, [x,y] doesn't match any possible list - it only matches lists with precisely two elements.
I would suggest replacing it with a separate function with an error case to print out the unexpected data in an error message so you can debug further, e.g.:
f [x,y] = (x, y)
f l = error $ "Unexpected list: " ++ show l
...
points <- fmap (map f . map ...)
As an addition to #GaneshSittampalam's answer, you could also do this with more graceful error handling using the Maybe monad, the mapM function from Control.Monad, and readMaybe from Text.Read. I would also recommend refactoring your code so that the parsing is its own function, it makes your main function much cleaner and easier to debug.
import Control.Monad (mapM)
import Text.Read (readMaybe)
toPoint :: [a] -> Maybe (a, a)
toPoint [x, y] = Just (x, y)
toPoint _ = Nothing
This is just a simple pattern matching function that returns Nothing if it gets a list with length not 2. Otherwise it turns it into a 2-tuple and wraps it in Just.
parseData :: String -> Maybe [(Int, Int)]
parseData text = do
-- returns Nothing if a non-Int is encountered
values <- mapM (mapM readMaybe . words) . lines $ text
-- returns Nothing if a line doesn't have exactly 2 values
mapM toPoint values
Your parsing can actually be simplified significantly by using mapM and readMaybe. The type of readMaybe is Read a => String -> Maybe a, and in this case since we've specified the type of parseData to return Maybe [(Int, Int)], the compiler can infer that readMaybe should have the local type of String -> Maybe Int. We still use lines and words in the same way, but now since we use mapM the type of the right hand side of the <- is Maybe [[Int]], so the type of values is [[Int]]. What mapM also does for us is if any of those actions fails, the overall computation exits early with Nothing. Then we simply use mapM toPoint to convert values into a list of points, but also with the failure mechanism built in. We actually could use the more general signature of parseData :: Read a => String -> Maybe [(a, a)], but it isn't necessary.
main = do
n <- readLn :: IO Int
points <- fmap parseData getContents
case points of
Just ps -> print $ meeting_point ps
Nothing -> putStrLn "Invalid data!"
Now we just use fmap parseData on getContents, making points have the type Maybe [(Int, Int)]. Finally, we pattern match on points to print out the result of the meeting_point computation or print a helpful message if something went wrong.
If you wanted even better error handling, you could leverage the Either monad in a similar fashion:
toPoint :: [a] -> Either String (a, a)
toPoint [x, y] = Right (x, y)
toPoint _ = Left "Invalid number of points"
readEither :: Read a => String -> Either String a
readEither text = maybe (Left $ "Invalid parse: " ++ text) Right $ readMaybe text
-- default value ^ Wraps output on success ^
-- Same definition with different type signature and `readEither`
parseData :: String -> Either String [(Int, Int)]
parseData text = do
values <- mapM (mapM readEither . words) . lines $ text
mapM toPoint values
main = do
points <- fmap parseData getContents
case points of
Right ps -> print $ meeting_point ps
Left err -> putStrLn $ "Error: " ++ err

Resources