GetOpt usage and foldl, flip, id - haskell

In the second example given in the documentation for System.Console.GetOpt, reproduced here, I am unable to understand or unpack this line:
(o,n,[] ) -> return (foldl (flip id) defaultOptions o, n)
What is this foldl doing, and how does it achieve it? What is the purpose of (flip id)? What is going on?
Code:
import System.Console.GetOpt
import Data.Maybe ( fromMaybe )
data Options = Options
{ optVerbose :: Bool
, optShowVersion :: Bool
, optOutput :: Maybe FilePath
, optInput :: Maybe FilePath
, optLibDirs :: [FilePath]
} deriving Show
defaultOptions = Options
{ optVerbose = False
, optShowVersion = False
, optOutput = Nothing
, optInput = Nothing
, optLibDirs = []
}
options :: [OptDescr (Options -> Options)]
options =
[ Option ['v'] ["verbose"]
(NoArg (\ opts -> opts { optVerbose = True }))
"chatty output on stderr"
, Option ['V','?'] ["version"]
(NoArg (\ opts -> opts { optShowVersion = True }))
"show version number"
, Option ['o'] ["output"]
(OptArg ((\ f opts -> opts { optOutput = Just f }) . fromMaybe "output")
"FILE")
"output FILE"
, Option ['c'] []
(OptArg ((\ f opts -> opts { optInput = Just f }) . fromMaybe "input")
"FILE")
"input FILE"
, Option ['L'] ["libdir"]
(ReqArg (\ d opts -> opts { optLibDirs = optLibDirs opts ++ [d] }) "DIR")
"library directory"
]
compilerOpts :: [String] -> IO (Options, [String])
compilerOpts argv =
case getOpt Permute options argv of
(o,n,[] ) -> return (foldl (flip id) defaultOptions o, n)
(_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: ic [OPTION...] files..."

The type of flip id is b -> (b -> c) -> c and you could find explanations here: Why does Haskell's "flip id" has this type?
The foldl (flip id) defaultOptions o sub-expression does the following:
Takes defaultOptions as initial value (defaultOptions has type Options)
Takes each element from o (each element has type Options -> Options)
Folds all elements using flip id function (it has b -> (b -> c) -> c type)
Since all of o elements changes corresponding option in the given configuration, the result of the foldl (flip id) defaultOptions o will be a configuration of all parsed options. All missed options replaced with their default values from defaultOptions.
The other parts of (o,n,[] ) -> return (foldl (flip id) defaultOptions o, n) expressions are pretty simple:
(o,n,[] ) -> matches a list of parsed options, a list of non-options and an empty list of errors
return (..., n) just puts the value (..., n) into monad IO (Options, [String])

(This is not strictly an answer to your question, but #soon asked me to post it anyway.)
The semantics of each command-line argument you define is described by
a transition function Options -> Options. Since you can pass many
arguments to a program, you end up with a list of such transition
functions [Options -> Options]. The goal is to compute the sum
effect of these transitions, i.e. an Options -> Options that applies
each transition in turn.
A particularly nice way of achieving this is to observe the structure
of endomorphisms a -> a for any type a:
id :: a -> a is the identity transition function that doesn't actually do anything
Given two transition functions f1, f2 :: a -> a, their composition
f1 . f2 corresponds precisely to applying both, in order. Note
also that this combination is associative, since doing f2 . f3 and
then f1 is the same as doing f3 followed by f1 . f2.
So we have a monoid!
The Haskell standard library base already contains this monoid with
the name Endo.
Using this, we can rewrite
foldl (flip id) defaultOptions o
in a much nicer way that, in my opinion, makes it immediately obvious what's happening here:
appEndo (fold o) defaultOptions
by changing the result type of options to [OptDescr (Endo Options)]; or, if you'd rather not, you can just add the extra Endo
line noise at combination time (by writing appEndo (foldMap Endo o) defaultOptions). Here, fold o :: Endo Options is the composite of all the individual transition functions, and appEndo (fold o) :: Options -> Options is how this resulting transition function is finally applied to the initial Options.
Note that this also works regardless of the data structure used for o: it will work for a list of transition functions, or a tree, or a Maybe, because of the associative property of the monoid at hand; and fold is polymorphic enough to expose this.

Related

Generate command line strings using optparse-applicative

Given a Parser a and a value of type a is it possible to generate the relevant command-line (in textual format)? (Basically, the exact reverse of what optparse-applicative is generally used for!)
For example, given something like...
data Args = {userName :: Text, userGroups :: Text }
parser :: Parser Args
parser = Args
<$> (strOption $ long "name")
<*> (many $ strOption $ long "group")
...how does one convert the following...
let args = Args { userName :: "testUser", userGroups :: ["system", "sudo"] }
...to...
--name=testUser --group=system --group=sudo
No, there is no way in general. The relevant bits are:
data Parser a
= forall x . MultP (Parser (x -> a)) (Parser x)
| forall x . BindP (Parser x) (x -> Parser a)
| -- ...
Since the xs of MultP and BindP are existentially quantified, the information about the suitable xs that could be used to produce your a is lost at runtime.

Writing an assembler in Haskell - mapM with state?

I'm writing a very simple two-pass assembler in Haskell and I've come across a scenario that I don't yet have the experience to solve. I think the solution is likely to involve monad transformers, which I don't really understand.
The assembler parses the assembly code into a list of Statements, which are either instructions or labels. Some Statements may refer to labels. The assembler needs to convert the Statements into Instructions, which involves eliminating the labels and substituting the label references with an appropriate value.
I have written the first pass of the assembler, which produces a [(String, Int)] representing a map from labels to addresses. I have also written the following function for translating a Statement into an Instruction:
stmtToInstruction :: Int -> [(String, Int)] -> Statement -> Either String [I.Instruction]
stmtToInstruction addr labels stmt = case stmt of
ADD d s1 s2 -> Right [I.ADD d s1 s2]
BEQL s1 s2 l -> case do label <- find (\e -> fst e == l) labels
let labelAddr = snd label
let relativeAddr = I.ImmS $ fromIntegral (labelAddr - addr)
return (I.BEQ s1 s2 relativeAddr) of
Just i -> Right [i]
Nothing -> Left $ "Label " ++ l ++ " not defined"
LABEL _ -> Right []
I've omitted several cases for brevity, but you can see all the possible results here:
ADD always succeeds and produces an instruction
BEQL can either succeed or fail, depending on whether a label is found
LABEL always succeeds, even though it produces no actual instructions
This works as expected. The problem I now have is writing this function:
replaceLabels :: [Statement] -> Either String [I.Instruction]
replaceLabels takes a list of statements, and runs stmtToInstruction on each one. The addr argument to stmtToInstruction must be the length of the [Instruction] accumulated so far. The output may either be a Left String, if one of the label references was invalid, or a Right [I.Instruction], if there were no errors.
mapM :: Monad m => (a -> m b) -> [a] -> m [b] gets us some of the way there, but provides no way to inject the current address into the (a -> m b) function. How do I make this work?
You're right: the StateT monad transformer will do the trick:
imapM :: (Traversable t, Monad m)
=> (Int -> a -> m b) -> t a -> m (t b)
imapM f = flip runStateT 0 .
mapM (\a ->
do
count <- get
put $! count + 1
f count a)
But writing the specialized version for lists might be better:
itraverse :: Applicative f
=> (Int -> a -> f b) -> [a] -> f [b]
itraverse f = go 0 where
go !_ [] = pure []
go !count (x:xs) = (:) <$> f count x <*> go (count + 1) xs
I've implemented a recursive solution that I'm sure is very inefficient. I'd still be interested to see the 'proper' way of doing this.
replaceLabels :: [Statement] -> Either String [I.Instruction]
replaceLabels [] = Right []
replaceLabels stmts#(s:ss) = replaceLabels' labels stmts 0
where labels = process stmts
replaceLabels' :: [(String, Int)] -> [Statement] -> Int -> Either String [I.Instruction]
replaceLabels' _ [] _ = Right []
replaceLabels' labels (s:ss) addr = do
instructions <- stmtToInstruction addr labels s
restInstructions <- replaceLabels' labels ss (addr + length instructions)
return (instructions ++ restInstructions)
I would start by changing
stmtToInstruction :: Int -> [(String, Int)] -> Statement -> Either String [I.Instruction]
into
stmtToInstruction :: [(String, Int)] -> Statement -> Either String (Int -> [I.Instruction])
That is, moving the function that takes the address into the Right branch of the Either. The reason is that label reference errors seem to be independent of addresses, so it's better to handle reference errors first and then worry about the address stuff in isolation.
This function resolves the references:
resolveRefs :: [(String,Int)] -> [Statement] -> Either String [Int -> [Instruction]]
resolveRefs environment = traverse (stmtToInstruction environment)
(traverse is equivalent to mapM but it only requires an Applicative constraint. They are different functions merely for historical reasons.)
Ok, after having handled the errors, lets now focus on the [Int -> [Instruction]] list. It seems that we have to map over it from the left while carrying an accumulated address that we must supply to each function. The mapAccumL function is perfect for this:
resolveAddrs :: [Int -> [Instruction]] -> [Instruction]
resolveAddrs funcs = mconcat . snd $ accumulate funcs
where
accumulate :: [Int -> [Instruction]] -> (Int,[[Instruction]])
accumulate = mapAccumL step 0
step address func = let is = func address in (address + length is,is)

State transformer: need a Nothing in a (Maybe Bool)

This is from the nicta course (hence List = [], Optional = Maybe, ...), so I'm not looking for a full solution, but I am stuck on a State Transformer question. The aim is to filter duplicates from a List and completely fail if passed any number > 100.
-- filtering :: Applicative f => (a -> f Bool) -> List a -> f (List a)
distinctF :: (Ord a, Num a) => List a -> Optional (List a)
distinctF lst = case runStateT (filtering go lst) S.empty of
Full (val, _) -> Full val
Empty -> Empty
where
--go :: a -> StateT (S.Set a) Optional Bool
go x = do
s <- getT
if x > 100 then do
return *?*Empty / False*?*
This typechecks while go = undefined, but I'm struggling to put Empty into as return wraps e.g. False in a Full/Just. fail gets me someway forward but I don't think that is the solution.
In practice I am probably missing a more important issue and would welcome enlightenment.
If the goal is to write function making both: unique filtering and failing on large input at the same time, you got the skeleton quite right:
distinctF :: (Ord a, Num a) => List a -> Optional (List a)
distinctF lst = evalStateT (go lst) S.empty -- evalStateT is your case runStateT part
where -- on empty input we just return empty list
go [] = return []
-- otherwise
go (x:xs)
-- we check whether we should 'fail'
-- for that we *lift* the value from underlying monad (Optional) into our StateT Optional
| x > 100 = lift $ Empty
| otherwise = do
-- the stuff to do
-- get the state, do nothing if x is in there
-- otherwise add x to the state and recurse
So for your question, you need to lift Empty, not return it.
OK, so I finally found a way, by realising that I could construct the precisely correct return type, rather than trying to rely on return
go x = do
if x > 100 then
StateT (\_ -> Empty) -- `return` a fail
else do
st <- getT
However, I am still not quite sure how <- unwraps both the StateT and the inner monadic container

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!"

Tagging functions in Haskell

An elementary Haskell question:
I would like to "tag functions" in Haskell: I have a list
scheme = [ f1, f2, f3, ... ]
which is built from some simple functions, some of them belonging to a certain group:
f1 :: a -> a
f1 a = ...
f2 :: a -> a -- "belongs to group"
f2 a = ...
f3 :: a -> a
f3 a = ...
f4 :: a -> a -- "belongs to group"
f4 a = ...
...
I want to create a smaller list, containing only the functions belonging to that subgroup:
filter belongsToGroup scheme
In Java, the functions would be subclasses of a Function class, some of them implementing an empty tagging interface FunctionGroup. The filter function could then be realized with the operator instanceof
I tried to understand how I could mimic this behaviour in Haskell (studying "type classes"), but had no success.
Any help?
Haskell actively discourages you from using type system escape hatches. (An instanceof-like construct would break some nice type system properties such as parametricity.) You most likely want to use this type:
type TaggedFunction a b = (a -> b, Bool)
Where first component is just the regular function you want to use, and the second component is True when the function belongs to the group, or False otherwise.
Then you filter TaggedFunctions like this: filter snd tfs
One approach to this problem would be to create a data type representing these functions.
data TaggedFunction a = UsefulFunction (a -> a)
| UselessFunction (a -> a)
f1 :: TaggedFunction a
f1 = UsefulFunction $ \x -> x
f2 :: TaggedFunction a
f2 = UselessFunction $ \x -> x
isUseful :: TaggedFunction a -> Bool
isUseful (UsefulFunction _) = True
isUseful _ = False
main :: IO ()
main = do
let fs = [f1, f2, f1, f2]
useful = filter isUseful fs
print $ (_f $ head useful) 4
This method is easily expandable to include more than two groups, and could even be automatically generated with e.g. Template Haskell.
Edit
After a bit of playing around, I like this refactor of TaggedFunction better.
data TaggedFunction a = Group1 { _f :: a }
| Group2 { _f :: a }
| Group3 { _f :: a }
f1 :: TaggedFunction (a -> a)
f1 = Group1 $ \x -> x
f2 :: TaggedFunction (a -> a)
f2 = Group2 $ \x -> x
isGroup :: Int -> TaggedFunction a -> Bool
isGroup 1 (Group1 _) = True
isGroup 2 (Group2 _) = True
isGroup 3 (Group3 _) = True
isGroup _ _ = False
main :: IO ()
main = do
let fs = [f1, f2, f1, f2]
useful = filter (isGroup 1) fs
print $ length useful
print $ (_f $ head useful) 4
Output:
λ> main
2
4
Note that isGroup is now not total (which I don't like), but it was more convenient than individual isGroupN functions for the purposes of this example.

Resources