printing a list of type signatures - haskell

I want to be able to type the following in ghci:
map showTypeSignature [(+),(-),show]
I want ghci to return the following list of Strings:
["(+) :: Num a => a -> a -> a","(-) :: Num a => a -> a -> a","show :: Show a => a -> String"]
Naturally, the first place that I run into trouble is that I cannot construct the first list, as the type signatures of the functions don't match. What can I do to construct such a list? How does ghci accomplish the printing of type signatures? Where is the ghci command :t defined (its source)?

What you're asking for isn't really possible. You cannot easily determine the type signature of a Haskell term from within Haskell. At run-time, there's hardly any type information available. The GHCi command :t is a GHCi command, not an interpreted Haskell function, for a reason.
To do something that comes close to what you want you'll have to use GHC itself, as a library. GHC offers the GHC API for such purposes. But then you'll not be able to use arbitrary Haskell terms, but will have to start with a String representation of your terms. Also, invoking the compiler at run-time will necessarily produce an IO output.

kosmikus is right, this doesn't really work out. And shouldn't, the static type system is one of Haskell's most distinguishing features!
However, you can emulate this for monomorphic functions quite well using the Dynamic existential:
showTypeSignature :: Dynamic -> String
showTypeSignature = show . dynTypeRep
Prelude Data.Dynamic> map showTypeSignature [toDyn (+), toDyn (-), toDyn (show)]
["Integer -> Integer -> Integer","Integer -> Integer -> Integer","() -> [Char]"]
As you see ghci had to boil the functions down to monomorphic type here for this to work, which particularly for show is patently useless.

The answers you have about why you can't do this are very good, but there may be another option. If you don't care about getting a Haskell list, and just want to see the types of a bunch of things, you can define a custom GHCi command, say :ts, that shows you the types of a list of things; to wit,
Prelude> :ts (+) (-) show
(+) :: Num a => a -> a -> a
(-) :: Num a => a -> a -> a
show :: Show a => a -> String
To do this, we use :def; :def NAME EXPR, where NAME is an identifier and EXPR is a Haskell expression of type String -> IO String, defines the GHCi command :NAME. Running :NAME ARGS evaluates EXPR ARGS to produce a string, and then runs the resulting string in GHCi. This is less confusing than it sounds. Here's what we do:
Prelude> :def ts return . unlines . map (":type " ++) . words
Prelude> :ts (+) (-) show
(+) :: Num a => a -> a -> a
(-) :: Num a => a -> a -> a
show :: Show a => a -> String
What's going on? This defines :ts to evaluate return . unlines . map (":t " ++) . words, which does the following:
words: Takes a string and splits it on whitespace; e.g., "(+) (-) show" becomes ["(+)", "(-)", "show"].
map (":type " ++): Takes each of the words from before and prepends ":type "; e.g., ["(+)", "(-)", "show"] becomes [":type (+)", ":type (-)", ":type show"]. Notice that we now have a list of GHCi commands.
unlines: Takes a list of strings and puts newlines after each one; e.g., [":type (+)", ":type (-)", ":type show"] becomes ":type (+)\n:type (-)\n:type show\n". Notice that if we pasted this string into GHCi, it would produce the type signatures we want.
return: Lifts a String to an IO String, because that's the type we need.
Thus, :ts name₁ name₂ ... nameₙ will evaluate :type name₁, :type name₂, …, :type nameₙ in succession and prints out the results. Again, you can't get a real list this way, but if you just want to see the types, this will work.

Related

Meaning of `$` when used as argument to map

I understand that the $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.
I am trying to understand what it means in this context:
map ($ 3) [(+),(-),(/),(*)]
With the following code:
instance Show (a -> b) where
show a = function
main = putStrLn $ show $ map ($ 3) [(+),(-),(/),(*)]
The output is
["function", "function", "function", "function"]
This doesn't help me understand the meaning of the $ here.
How can I display more helpful output?
($) :: (a -> b) -> a -> b is a function that takes a function as first parameter, and a value as second and returns the value applied to that function.
For example:
Prelude> (1+) $ 2
3
The expression ($ 3) is an example of infix operator sectioning [Haskell-wiki]. ($ 3) is short for \f -> f $ 3, or simpler \f -> f 3. It thus is a function that takes a function and applies 3 to that function.
For your expression:
map ($ 3) [(+),(-),(/),(*)]
the output is thus equivalent to:
[(3+), (3-), (3/), (3*)] :: Fractional a => [a -> a]
Since (+), (-), (*) :: Num a => a -> a -> a work with types that are members of the Num typeclass, and (/) :: Fractional a => a -> a -> a works with types that are members of the Fractional type class, and all Fractional types are num types as well, 3 is here a Fractional type, and the list thus contains functions that are all of the type a -> a with a a member of Fractional.
How can I display more helpful output?
The compiler does not keep track of the expressions, as specified in the Haskell wiki page on Show instance for functions [Haskell-wiki].
The Haskell compiler doesn't maintain the expressions as they are, but translates them to machine code or some other low-level representation. The function \x -> x - x + x :: Int -> Int might have been optimized to \x -> x :: Int -> Int. If it's used anywhere, it might have been inlined and optimized to nothing. The variable name x is not stored anywhere. (...)
So we can not "look inside" the function and derive an expression that is human-readable.

Haskell Pattern Matching (beginner)

I have to implement a small programm in Haskell that increments/decrements a result by what in the console line is. For example if we have -a in the console the results must be 0, if -b the result must be incremented with 6 and so on. I have to do this with pattern matching.
I haven't used Haskell until now and I find it pretty hard to understand. I have this to start with:
import System.Environment
main = getArgs >>= print . (foldr apply 0) . reverse
apply :: String -> Integer -> Integer
I don't understand what in the main is. What does it make and the reverse from end, what does it do? As I've read on the internet the getArgs function gives me the values from the console line. But how can I use them? Are there are equivalent functions like for/while in Haskell?
Also, if you have some examples or maybe could help me, I will be very thankful.
Thanks!
This is not beginner-friendly code. Several shortcuts are taken there to keep the code very compact (and in pointfree form). The code
main = getArgs >>= print . (foldr apply 0) . reverse
can be expanded as follows
main = do
args <- getArgs
let reversedArgs = reverse args
result = foldr apply 0 reversedArgs
print result
The result of this can be seen as follows. If the command line arguments are, say, args = ["A","B","C"], then we get reversedArgs = ["C","B","A"] and finally
result = apply "C" (apply "B" (apply "A" 0))
since foldr applies the function apply in such way.
Honestly, I'm unsure about why the code uses reverse and foldr for your task. I would have considered foldl (or, to improve performance, foldl') instead.
I expect the exercise is not to touch the given code, but to expand on it to perform your function. It defines a complicated-looking main function and declares the type of a more straight forward apply, which is called but not defined.
import System.Environment -- contains the function getArgs
-- main gets arguments, does something to them using apply, and prints
main = getArgs >>= print . (foldr apply 0) . reverse
-- apply must have this type, but what it does must be elsewhere
apply :: String -> Integer -> Integer
If we concentrate on apply, we see that it receives a string and an integer, and returns an integer. This is the function we have to write, and it can't decide control flow, so we can just get to it while hoping the argument handling works out.
If we do want to figure out what main is up to, we can make a few observations. The only integer in main is 0, so the first call must get that as its second argument; later ones will be chained with whatever is returned, as that's how foldr operates. r stands for from the right, but the arguments are reversed, so this still processes arguments from the left.
So I could go ahead and just write a few apply bindings to make the program compile:
apply "succ" n = succ n
apply "double" n = n + n
apply "div3" n = n `div` 3
This added a few usable operations. It doesn't handle all possible strings.
$ runhaskell pmb.hs succ succ double double succ div3
3
$ runhaskell pmb.hs hello?
pmb.hs: pmb.hs:(5,1)-(7,26): Non-exhaustive patterns in function apply
The exercise should be about how you handle the choice of operation based on the string argument. There are several options, including distinct patterns as above, pattern guards, case and if expressions.
It can be useful to examine the used functions to see how they might fit together. Here's a look at a few of the used functions in ghci:
Prelude> import System.Environment
Prelude System.Environment> :t getArgs
getArgs :: IO [String]
Prelude System.Environment> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Prelude System.Environment> :t print
print :: Show a => a -> IO ()
Prelude System.Environment> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude System.Environment> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude System.Environment> :t reverse
reverse :: [a] -> [a]
This shows that all the strings come out of getArgs, it and print operate in the IO monad, which must be the m in >>=, and . transfers results from the right function into arguments for the left function. The type signature alone doesn't tell us what order foldr handles things, though, or what reverse does (though it can't create new values, only reorder including repetition).
As a last exercise, I'll rewrite the main function in a form that doesn't switch directions as many times:
main = print . foldl (flip apply) 0 =<< getArgs
This reads from right to left in a data flow sense and handles arguments from left to right because foldl performs left-associative folding. flip is just there to match the argument order for apply.
As suggested in the comment, hoogle is a great tool.
To find out what exactly you get from getArgs you can search for it on hoogle:
https://hackage.haskell.org/package/base-4.11.1.0/docs/System-Environment.html#v:getArgs
As you can see, it's of type IO [String].
Since I don't know how familiar you are with the IO abstractions yet, we'll just say that the right part of >>= gets those as argument.
The arguments for a call like ./a.out -a -b --asdf Hi will then be a list of strings:
["-a", "-b", "--asdf", "Hi"].
The fold + reverse in the main will then do some magic, and your apply function will be called with each string in the list and the previous return value (0 for the first invocation).
In Haskell, String is the same as [Char] with a bit of compiler sugar, so you can match on strings like you would on regular lists in your definition of apply.

Why does the type of a function change when it comes out of a monad in GHCi [duplicate]

This question already has an answer here:
Why does `peek` with a polymorphic Ptr return GHC.Prim.Any when used with a bind?
(1 answer)
Closed 6 years ago.
Something changes about the type of a function when it comes out of a monad.
In GHCI:
> :t map
map :: (a -> b) -> [a] -> [b]
> a <- return map
> :t a
a :: (GHC.Prim.Any -> GHC.Prim.Any)
-> [GHC.Prim.Any] -> [GHC.Prim.Any]
This change makes it hard to store the function in a higher rank type.
What is happening here and can I make it not happen?
(Also doesn't this violate one of the monad laws?)
First of all, there is no point in doing anything like a <- return map - its the same as let a = map, which works just fine. That said, I don't think that is your question...
Checking out the documentation of GHC.Prim.Any which gives us a big hint as to the role of Any.
It's also used to instantiate un-constrained type variables after type
checking. For example, length has type
length :: forall a. [a] -> Int
and the list datacon for the empty list has type
[] :: forall a. [a]
In order to compose these two terms as length [] a
type application is required, but there is no constraint on the
choice. In this situation GHC uses Any
(In terms of type application syntax, that looks like length #Any ([] #Any *))
The problem is that when GHCi sees x <- return map it tries to desugar it to return map >>= \x -> ... but the ... part is whatever you enter next into GHCi. Normally it would figure out what the type variables of map are going to be instantiated to (or whether they even should be instantiated to anything) based the ..., but since it has nothing there.
Another key point that #sepp2k points out is that x can't be given a polymorphic type because (>>=) expects (on its RHS) a rank-1 function, and that means its argument can't be polymorphic. (Loosening this condition pushes you straight into RankNTypes at which point you lose the ability to infer types reliably.)
Therefore, needing x to be monomorphic and having no information to help it instantiate the type variables that prevent x from being monomorphic, it defaults to using Any. That means that instead of (a -> b) -> [a] -> [b] you get (Any -> Any) -> [Any] -> [Any].

Why can't I use the type `Show a => [Something -> a]`?

I have a record type say
data Rec {
recNumber :: Int
, recName :: String
-- more fields of various types
}
And I want to write a toString function for Rec :
recToString :: Rec -> String
recToString r = intercalate "\t" $ map ($ r) fields
where fields = [show . recNumber, show . recName]
This works. fields has type [Rec -> String]. But I'm lazy and I would prefer writing
recToString r = intercalate "\t" $ map (\f -> show $ f r) fields
where fields = [recNumber, recName]
But this doesn't work. Intuitively I would say fields has type Show a => [Rec -> a] and this should be ok. But Haskell doesn't allow it.
I'd like to understand what is going on here. Would I be right if I said that in the first case I get a list of functions such that the 2 instances of show are actually not the same function, but Haskell is able to determine which is which at compile time (which is why it's ok).
[show . recNumber, show . recName]
^-- This is show in instance Show Number
^-- This is show in instance Show String
Whereas in the second case, I only have one literal use of show in the code, and that would have to refer to multiple instances, not determined at compile time ?
map (\f -> show $ f r) fields
^-- Must be both instances at the same time
Can someone help me understand this ? And also are there workarounds or type system expansions that allow this ?
The type signature doesn't say what you think it says.
This seems to be a common misunderstanding. Consider the function
foo :: Show a => Rec -> a
People frequently seem to think this means that "foo can return any type that it wants to, so long as that type supports Show". It doesn't.
What it actually means is that foo must be able to return any possible type, because the caller gets to choose what the return type should be.
A few moments' thought will reveal that foo actually cannot exist. There is no way to turn a Rec into any possible type that can ever exist. It can't be done.
People often try to do something like Show a => [a] to mean "a list of mixed types but they all have Show". That obviously doesn't work; this type actually means that the list elements can be any type, but they still have to be all the same.
What you're trying to do seems reasonable enough. Unfortunately, I think your first example is about as close as you can get. You could try using tuples and lenses to get around this. You could try using Template Haskell instead. But unless you've got a hell of a lot of fields, it's probably not even worth the effort.
The type you actually want is not:
Show a => [Rec -> a]
Any type declaration with unbound type variables has an implicit forall. The above is equivalent to:
forall a. Show a => [Rec -> a]
This isn't what you wan't, because the a must be specialized to a single type for the entire list. (By the caller, to any one type they choose, as MathematicalOrchid points out.) Because you want the a of each element in the list to be able to be instantiated differently... what you are actually seeking is an existential type.
[exists a. Show a => Rec -> a]
You are wishing for a form of subtyping that Haskell does not support very well. The above syntax is not supported at all by GHC. You can use newtypes to sort of accomplish this:
{-# LANGUAGE ExistentialQuantification #-}
newtype Showy = forall a. Show a => Showy a
fields :: [Rec -> Showy]
fields = [Showy . recNumber, Showy . recName]
But unfortunatley, that is just as tedious as converting directly to strings, isn't it?
I don't believe that lens is capable of getting around this particular weakness of the Haskell type system:
recToString :: Rec -> String
recToString r = intercalate "\t" $ toListOf (each . to fieldShown) fields
where fields = (recNumber, recName)
fieldShown f = show (f r)
-- error: Couldn't match type Int with [Char]
Suppose the fields do have the same type:
fields = [recNumber, recNumber]
Then it works, and Haskell figures out which show function instance to use at compile time; it doesn't have to look it up dynamically.
If you manually write out show each time, as in your original example, then Haskell can determine the correct instance for each call to show at compile time.
As for existentials... it depends on implementation, but presumably, the compiler cannot determine which instance to use statically, so a dynamic lookup will be used instead.
I'd like to suggest something very simple instead:
recToString r = intercalate "\t" [s recNumber, s recName]
where s f = show (f r)
All the elements of a list in Haskell must have the same type, so a list containing one Int and one String simply cannot exist. It is possible to get around this in GHC using existential types, but you probably shouldn't (this use of existentials is widely considered an anti-pattern, and it doesn't tend to perform terribly well). Another option would be to switch from a list to a tuple, and use some weird stuff from the lens package to map over both parts. It might even work.

Specific type inference using uncurry function

I've been playing with the uncurry function in GHCi and I've found something I couldn't quite get at all. When I apply uncurry to the (+) function and bind that to some variable like in the code below, the compiler infers its type to be specific to Integer:
Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer
However, when ask for the type of the following expression I get (what I expect to be) the correct result:
Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a
What would cause that? Is it particular to GHCi?
The same applies to let add' = (+).
NOTE: I could not reproduce that using a compiled file.
This has nothing to do with ghci. This is the monomorphism restriction being irritating. If you try to compile the following file:
add = uncurry (+)
main = do
print $ add (1,2 :: Int)
print $ add (1,2 :: Double)
You will get an error. If you expand:
main = do
print $ uncurry (+) (1,2 :: Int)
print $ uncurry (+) (1,2 :: Double)
Everything is fine, as expected. The monomorphism restriction refuses to make something that "looks like a value" (i.e. defined with no arguments on the left-hand side of the equals) typeclass polymorphic, because that would defeat the caching that would normally occur. Eg.
foo :: Integer
foo = expensive computation
bar :: (Num a) => a
bar = expensive computation
foo is guaranteed only to be computed once (well, in GHC at least), whereas bar will be computed every time it is mentioned. The monomorphism restriction seeks to save you from the latter case by defaulting to the former when it looks like that's what you wanted.
If you only use the function once (or always at the same type), type inference will take care of inferring the right type for you. In that case ghci is doing something slightly different by guessing sooner. But using it at two different types shows what is going on.
When in doubt, use a type signature (or turn off the wretched thing with {-# LANGUAGE NoMonomorphismRestriction #-}).
There's magic involved in extended defaulting rules with ghci. Basically, among other things, Num constraints get defaulted to Integer and Floating constraints to Double, when otherwise there would be an error (in this case, due to the evil monomorphism restriction).

Resources