Haskell: Get caller function name - haskell

In Haskell, is there a way to get the caller function name? Of course I could hard-code it, but that turns into a maintenance burden: If someone were to rename the function, nothing is forcing them to rename the hard-coded name.
A contrived example:
f1 :: String
f1 = "f1" -- can this be automated?

You can do this with GHC's CallStack functionality.
import GHC.Stack ( HasCallStack, getCallStack, callStack )
foo :: HasCallStack => String -> String
foo s = let ((name, _):_) = getCallStack callStack
in s <> ": " <> name
main :: HasCallStack => IO ()
main = putStrLn $ foo "This string is being passed to"
Produces output This string is being passed to: foo
See my link above for a full description, but basically you can ask to have access to a (partial) call stack in a function by including a HasCallStack constraint. Then callStack gets a CallStack, which is isomorphic to [(String, SrcLoc)], where the first element of each pair is a function name; getCallStack converts the abstract CallStack type into an actual list of pairs.
(The docs seem to claim that HasCallStack constraints can be inferred, but in my very brief experiments that wasn't happening; if I used callStack in a function with no signature I was just getting an empty call stack; probably best to explicitly write a signature with a HasCallStack constraint)

A kernel of an idea: make f1 be a parameterized thing. This will make it possible to put the code name and the string representing the code name together, to reduce the chances that somebody renames one without the other. So:
f1Raw :: String -> String
f1Raw name = name
f1 :: String
f1 = f1Raw "f1"
With a bit of Template Haskell hackery, it is likely that you could make an interface withName :: String -> Q [Decl] or so that let you write something like this as a shorthand for this pattern:
-- f1Raw exactly as before
f1Raw :: String -> String
f1Raw name = name
-- this next line...
$(withName "f1")
-- ...would expand to these two:
-- f1 :: String
-- f1 = f1Raw "f1"
The behavior of withName would be, roughly:
Take the given String, append "Raw", and create a Name for the corresponding thing in the current module.
Use introspection to get the type of the raw thing, check that it starts out String -> ..., then strip the String -> bit and create a Decl that declares f1 :: ....
Implement f1 = f1Raw "f1" as a second Decl.

Related

What is the type keyword in Haskell

Stumbled on the type keyword in Haskell:
type Item = String
but not sure what it does, how to use it or how it is different from data. The online google search has been of no help.
I tried implementing it in a code like this:
import System.IO
main = do
putStrLn "Hello, what's your name?"
type Item = String
let test :: Item
test = "chris"
putStrLn test
but I got an error
parse error on input ‘type’
Please in a lay man's term what is type and how can it be used and how is it different from data?
It is a type alias. It means that you can use Item in your code where you can use String instead.
A type alias is often used when you for example want to give a name to more complex types. For example:
import Data.Map(Map)
type Dictionary = Map String String
here you thus can use Dictionary instead of each time writing Map String String.
It is furthermore often used if you want to specify that you are working with Items, the alias is then used in the type signature and in the documentation, which is often better than writing String.
It is also used if you do not yet know what type you will use for a specific object. By using a type alias, you can the work with Item, and later if you change your made define a type for Item or make it an alias of another type. This makes it more convenient to change the types.
I tried implementing it in a code like this:
import System.IO
main = do
putStrLn "Hello, what's your name?"
type Item = String
let test :: Item
test = "chris"
putStrLn test
A type alias is defined at the top level, so not in a do block, that would make a type definition locally scoped. While, like #moonGoose says, there are some proposals to make type definitions more locally scoped, currently it is not the case.
You can define the type alias like:
import System.IO
type Item = String
main = do
putStrLn "Hello, what's your name?"
let test :: Item
test = "chris"
putStrLn test
type A = B
means exactly the same as
typedef B A
in C or C++, and it behaves basically the same as simply
a = b
except that A and B are type-level entities, not value-level ones. For example
Prelude> type A = Int
Prelude> :i A
type A = Int -- Defined at <interactive>:1:1
Prelude> a = 37
Prelude> a
37
Because now A = Int, I can then use the type identifier A exactly everywhere I could also use Int directly:
Prelude> 37 :: Int
37
Prelude> 37 :: A
37
and even
Prelude> (37 :: Int) :: A
37
Note that there is no type conversion going on here, like you might have in other languages. Int and A are simply different names for the same type, so annotating with both is merely a tautology.
Contrast this with data (or newtype), which define a new, separate type which just happens to contain the, well, data of the specified type.
Prelude> data A' = A' { getA :: Int }
Prelude> (37 :: Int) :: A'
<interactive>:12:2: error:
• Couldn't match expected type ‘A'’ with actual type ‘Int’
• In the expression: (37 :: Int) :: A'
In an equation for ‘it’: it = (37 :: Int) :: A'

When do I need type annotations?

Consider these functions
{-# LANGUAGE TypeFamilies #-}
tryMe :: Maybe Int -> Int -> Int
tryMe (Just a) b = a
tryMe Nothing b = b
class Test a where
type TT a
doIt :: TT a -> a -> a
instance Test Int where
type TT Int = Maybe Int
doIt (Just a) b = a
doIt (Nothing) b = b
This works
main = putStrLn $ show $ tryMe (Just 2) 25
This doesn't
main = putStrLn $ show $ doIt (Just 2) 25
{-
• Couldn't match expected type ‘TT a0’ with actual type ‘Maybe a1’
The type variables ‘a0’, ‘a1’ are ambiguous
-}
But then, if I specify the type for the second argument it does work
main = putStrLn $ show $ doIt (Just 2) 25::Int
The type signature for both functions seem to be the same. Why do I need to annotate the second parameter for the type class function? Also, if I annotate only the first parameter to Maybe Int it still doesn't work. Why?
When do I need to cast types in Haskell?
Only in very obscure, pseudo-dependently-typed settings where the compiler can't proove that two types are equal but you know they are; in this case you can unsafeCoerce them. (Which is like C++' reinterpret_cast, i.e. it completely circumvents the type system and just treats a memory location as if it contains the type you've told it. This is very unsafe indeed!)
However, that's not what you're talking about here at all. Adding a local signature like ::Int does not perform any cast, it merely adds a hint to the type checker. That such a hint is needed shouldn't be surprising: you didn't specify anywhere what a is supposed to be; show is polymorphic in its input and doIt polymorphic in its output. But the compiler must know what it is before it can resolve the associated TT; choosing the wrong a might lead to completely different behaviour from the intended.
The more surprising thing is, really, that sometimes you can omit such signatures. The reason this is possible is that Haskell, and more so GHCi, has defaulting rules. When you write e.g. show 3, you again have an ambiguous a type variable, but GHC recognises that the Num constraint can be “naturally” fulfilled by the Integer type, so it just takes that pick.
Defaulting rules are handy when quickly evaluating something at the REPL, but they are fiddly to rely on, hence I recommend you never do it in a proper program.
Now, that doesn't mean you should always add :: Int signatures to any subexpression. It does mean that, as a rule, you should aim for making function arguments always less polymorphic than the results. What I mean by that: any local type variables should, if possible, be deducable from the environment. Then it's sufficient to specify the type of the final end result.
Unfortunately, show violates that condition, because its argument is polymorphic with a variable a that doesn't appear in the result at all. So this is one of the functions where you don't get around having some signature.
All this discussion is fine, but it hasn't yet been stated explicitly that in Haskell numeric literals are polymorphic. You probably knew that, but may not have realized that it has bearing on this question. In the expression
doIt (Just 2) 25
25 does not have type Int, it has type Num a => a — that is, its type is just some numeric type, awaiting extra information to pin it down exactly. And what makes this tricky is that the specific choice might affect the type of the first argument. Thus amalloy's comment
GHC is worried that someone might define an instance Test Integer, in which case the choice of instance will be ambiguous.
When you give that information — which can come from either the argument or the result type (because of the a -> a part of doIt's signature) — by writing either of
doIt (Just 2) (25 :: Int)
doIt (Just 2) 25 :: Int -- N.B. this annotates the type of the whole expression
then the specific instance is known.
Note that you do not need type families to produce this behavior. This is par for the course in typeclass resolution. The following code will produce the same error for the same reason.
class Foo a where
foo :: a -> a
main = print $ foo 42
You might be wondering why this doesn't happen with something like
main = print 42
which is a good question, that leftroundabout has already addressed. It has to do with Haskell's defaulting rules, which are so specialized that I consider them little more than a hack.
With this expression:
putStrLn $ show $ tryMe (Just 2) 25
We've got this starting information to work from:
putStrLn :: String -> IO ()
show :: Show a => a -> String
tryMe :: Maybe Int -> Int -> Int
Just :: b -> Maybe b
2 :: Num c => c
25 :: Num d => d
(where I've used different type variables everywhere, so we can more easily consider them all at once in the same scope)
The job of the type-checker is basically to find types to choose for all of those variables, so and then make sure that the argument and result types line up, and that all the required type class instances exist.
Here we can see that tryMe applied to two arguments is going to be an Int, so a (used as input to show) must be Int. That requires that there is a Show Int instance; indeed there is, so we're done with a.
Similarly tryMe wants a Maybe Int where we have the result of applying Just. So b must be Int, and our use of Just is Int -> Maybe Int.
Just was applied to 2 :: Num c => c. We've decided it must be applied to an Int, so c must be Int. We can do that if we have Num Int, and we do, so c is dealt with.
That leaves 25 :: Num d => d. It's used as the second argument to tryMe, which is expecting an Int, so d must be Int (again discharging the Num constraint).
Then we just have to make sure all the argument and result types line up, which is pretty obvious. This is mostly rehashing the above since we made them line up by choosing the only possible value of the type variables, so I won't get into it in detail.
Now, what's different about this?
putStrLn $ show $ doIt (Just 2) 25
Well, lets look at all the pieces again:
putStrLn :: String -> IO ()
show :: Show a => a -> String
doIt :: Test t => TT t -> t -> t
Just :: b -> Maybe b
2 :: Num c => c
25 :: Num d => d
The input to show is the result of applying doIt to two arguments, so it is t. So we know that a and t are the same type, which means we need Show t, but we don't know what t is yet so we'll have to come back to that.
The result of applying Just is used where we want TT t. So we know that Maybe b must be TT t, and therefore Just :: _b -> TT t. I've written _b using GHC's partial type signature syntax, because this _b is not like the b we had before. When we had Just :: b -> Maybe b we could pick any type we liked for b and Just could have that type. But now we need some specific but unknown type _b such that TT t is Maybe _b. We don't have enough information to know what that type is yet, because without knowing t we don't know which instance's definition of TT t we're using.
The argument of Just is 2 :: Num c => c. So we can tell that c must also be _b, and this also means we're going to need a Num _b instance. But since we don't know what _b is yet we can't check whether there's a Num instance for it. We'll come back to it later.
And finally the 25 :: Num d => d is used where doIt wants a t. Okay, so d is also t, and we need a Num t instance. Again, we still don't know what t is, so we can't check this.
So all up, we've figured out this:
putStrLn :: String -> IO ()
show :: t -> String
doIt :: TT t -> t -> t
Just :: _b -> TT t
2 :: _b
25 :: t
And have also these constraints waiting to be solved:
Test t, Num t, Num _b, Show t, (Maybe _b) ~ (TT t)
(If you haven't seen it before, ~ is how we write a constraint that two type expressions must be the same thing)
And we're stuck. There's nothing further we can figure out here, so GHC is going to report a type error. The particular error message you quoted is complaining that we can't tell that TT t and Maybe _b are the same (it calls the type variables a0 and a1), since we didn't have enough information to select concrete types for them (they are ambiguous).
If we add some extra type signatures for parts of the expression, we can go further. Adding 25 :: Int1 immediately lets us read off that t is Int. Now we can get somewhere! Lets patch that into the constrints we had yet to solve:
Test Int, Num Int, Num _b, Show Int, (Maybe _b) ~ (TT Int)
Num Int and Show Int are obvious and built in. We've got Test Int too, and that gives us the definition TT Int = Maybe Int. So (Maybe _b) ~ (Maybe Int), and therefore _b is Int too, which also allows us to discharge that Num _b constraint (it's Num Int again). And again, it's easy now to verify all the argument and result types match up, since we've filled in all the type variables to concrete types.
But why didn't your other attempt work? Lets go back to as far as we could get with no additional type annotation:
putStrLn :: String -> IO ()
show :: t -> String
doIt :: TT t -> t -> t
Just :: _b -> TT t
2 :: _b
25 :: t
Also needing to solve these constraints:
Test t, Num t, Num _b, Show t, (Maybe _b) ~ (TT t)
Then add Just 2 :: Maybe Int. Since we know that's also Maybe _b and also TT t, this tells us that _b is Int. We also now know we're looking for a Test instance that gives us TT t = Maybe Int. But that doesn't actually determine what t is! It's possible that there could also be:
instance Test Double where
type TT Double = Maybe Int
doIt (Just a) _ = fromIntegral a
doIt Nothing b = b
Now it would be valid to choose t as either Int or Double; either would work fine with your code (since the 25 could also be a Double), but would print different things!
It's tempting to complain that because there's only one instance for t where TT t = Maybe Int that we should choose that one. But the instance selection logic is defined not to guess this way. If you're in a situation where it's possible that another matching instance should exist, but isn't there due to an error in the code (forgot to import the module where it's defined, for example), then it doesn't commit to the only matching instance it can see. It only chooses an instance when it knows no other instance could possibly apply.2
So the "there's only one instance where TT t = Maybe Int" argument doesn't let GHC work backward to settle that t could be Int.
And in general with type families you can only "work forwards"; if you know the type you're applying a type family to you can tell from that what the resulting type should be, but if you know the resulting type this doesn't identify the input type(s). This is often surprising, since ordinary type constructors do let us "work backwards" this way; we used this above to conclude from Maybe _b = Maybe Int that _b = Int. This only works because with new data declarations, applying the type constructor always preserves the argument type in the resulting type (e.g. when we apply Maybe to Int, the resulting type is Maybe Int). The same logic doesn't work with type families, because there could be multiple type family instances mapping to the same type, and even when there isn't there is no requirement that there's an identifiable pattern connecting something in the resulting type to the input type (I could have type TT Char = Maybe (Int -> Double, Bool).
So you'll often find that when you need to add a type annotation, you'll often find that adding one in a place whose type is the result of a type family doesn't work, and you'll need to pin down the input to the type family instead (or something else that is required to be the same type as it).
1 Note that the line you quoted as working in your question main = putStrLn $ show $ doIt (Just 2) 25::Int does not actually work. The :: Int signature binds "as far out as possible", so you're actually claiming that the entire expression putStrLn $ show $ doIt (Just 2) 25 is of type Int, when it must be of type IO (). I'm assuming when you really checked it you put brackets around 25 :: Int, so putStrLn $ show $ doIt (Just 2) (25 :: Int).
2 There are specific rules about what GHC considers "certain knowledge" that there could not possibly be any other matching instances. I won't get into them in detail, but basically when you have instance Constraints a => SomeClass (T a), it has to be able to unambiguously pick an instance only by considering the SomeClass (T a) bit; it can't look at the constraints left of the => arrow.

Safe Record field query

Is there a clean way to avoid the following boilerplate:
Given a Record data type definition....
data Value = A{ name::String } | B{ name::String } | C{}
write a function that safely returns name
getName :: Value -> Maybe String
getName A{ name=x } = Just x
getName B{ name=x } = Just x
getName C{} = Nothing
I know you can do this with Template Haskell, I am looking for a cleaner soln than that, perhaps a GHC extension or something else I've overlooked.
lens's Template Haskell helpers do the right thing when they encounter partial record fields.
{-# LANGUAGE TemplateHaskell #-}
import Control.Applicative
import Control.Lens
data T = A { _name :: String }
| B { _name :: String }
| C
makeLenses ''T
This'll generate a Traversal' called name that selects the String inside the A and B constructors and does nothing in the C case.
ghci> :i name
name :: Traversal' T String -- Defined at test.hs:11:1
So we can use the ^? operator (which is a flipped synonym for preview) from Control.Lens.Fold to pull out Maybe the name.
getName :: T -> Maybe String
getName = (^? name)
You can also make Prism's for the constructors of your datatype, and choose the first one of those which matches using <|>. This version is useful when the fields of your constructors have different names, but you do have to remember to update your extractor function when you add constructors.
makePrisms ''T
getName' :: T -> Maybe String
getName' t = t^?_A <|> t^?_B
lens is pretty useful!
Why don't you use a GADT? I do not know if you are interested in using only records. But, I fell that GADTs provide a clean solution to your problem, since you can restrict what constructors are valid by refining types.
{-# LANGUAGE GADTs #-}
module Teste where
data Value a where
A :: String -> Value String
B :: String -> Value String
C :: Value ()
name :: Value String -> String
name (A s) = s
name (B s) = s
Notice that both A and B produce Value String values while C produces Value (). When you define function
name :: Value String -> String
it specifically says that you can only pass a value that has a string in it. So, you can only pattern match on A or B values. This is useful to avoid the need of Maybe in code.

How to convert IO Int to String in Haskell?

I'm learning to use input and output in Haskell. I'm trying to generate a random number and output it to another file. The problem is that the random number seems to be returning an IO Int, something that I can't convert to a String using show.
Could someone give me a pointer here?
It's helpful if you show us the code you've written that isn't working.
Anyway, you are in a do block and have written something like this, yes?
main = do
...
writeFile "some-file.txt" (show generateRandomNumberSomehow)
...
You should instead do something like this:
main = do
...
randomNumber <- generateRandomNumberSomehow
writeFile "some-file.txt" (show randomNumber)
...
The <- operator binds the result of the IO Int value on the right to the Int-valued variable on the left. (Yes, you can also use this to bind the result of an IO String value to a String-valued variable, etc.)
This syntax is only valid inside a do block. It's important to note that the do block will itself result in an IO value --- you can't launder away the IO-ness.
dave4420's answer is what you want here. It uses the fact that IO is a Monad; that's why you can use the do notation.
However, I think it's worth mentioning that the concept of "applying a function to a value that's not 'open', but inside some wrapper" is actually more general than IO and more general than monads. It's what we have the Functor class for.
For any functor f (this could, for instance, be Maybe or [] or IO), when you have some value
wrapped :: f t (for instance wrapped :: Maybe Int), you can use fmap to apply a function
t -> t' to it (like show :: Int -> String) and get a
wrappedApplied :: f t' (like wrappedApplied :: Maybe String).
In your example, it would be
genRandomNumAsString :: IO String
genRandomNumAsString = fmap show genRandomNumPlain

Using haskell read and typeclasses - ambiguous type variable error

I have an ambiguous type variable error on the definition of "trial" below, I am wondering if there is anything that can be done to make this situation work? I want to really just deal with instances and not explicit data types (such as the MO1, MO2 included below).
module Tc102 where
class (Show a, Read a) => MyObj a where
alpha :: a->String
beta :: a->Int
data MO1 = MO1 { a1 :: String, b1 :: Int } deriving (Show,Read)
data MO2 = MO2 { a2 :: String, b2 :: Int } deriving (Show,Read)
instance MyObj MO1 where
alpha = a1
beta = b1
instance MyObj MO2 where
alpha = a2
beta = b2
a = MO1 "a" 3
b = MO2 "b" 4
test :: MyObj a => a->String
test = alpha
showMe :: (MyObj a)=> a -> String
showMe = show
readMe :: (MyObj a) => String -> a
readMe = read
trial :: MyObj a => a -> String
trial = test . readMe . showMe
thanks in advance all! I fear however i might need to go to a helper function that would convert old ADT to the 'latest versions...
Simon
EDIT To clarify, imagine that I first show to a file, then later reload the object. Then the function i have is more like
trial :: String -> Int
trial s = beta x
where x = readMe s
You get the error because the compiler doesn't know what concrete type readMe should return, since all that test requires is that it be an instance of MyObj. It could be MO1, MO2, or something else entirely, and readMe could return any of those.
Assuming you want readMe . showMe to act like id and output the same type given as input, the quick-and-dirty way is to define a function that does just that, and give it a type signature that equates the input and output types:
trial :: MyObj a => a -> String
trial = test . readShowMe
where readShowMe :: MyObj a => a -> a
readShowMe = readMe . showMe
Now the compiler can figure out what concrete type to give to test as input.
You can't read compile-time type from run-time file. You should explicitly implement run-time type-varying value.
As example:
data AnyMyObj = forall a . MyObj a => AnyMyObj a
test :: AnyMyObj -> String
test (AnyMyObj x) = alpha x
showMe :: AnyMyObj -> String
showMe (AnyMyObj x) = show x
readMe :: String -> AnyMyObj
readMe s = AnyMyObj (read s :: MO1) -- maybe something more complicated
trial :: AnyMyObj -> String
trial = test . readMe . showMe
There are fancy tricks to this, and the ultimate answer is indeed to read into some sort of existential. For a fancy exposition of a very powerful/general way to do this, see Oleg's Typed-tagless final lecture notes: http://okmij.org/ftp/tagless-final/course/#type-checking.
But that's serious overkill for an example like yours -- the trickiness generally enters when you have tree structures, and especially when you have tree structures representing lambda terms.
For your purposes, ony's example above is roughly right.
But keep in mind that even though you can create new instances of MyObj, your read function will only be able to read a fixed universe, at least without high-level hackery.
So this is a case where I'd question whether you want a typeclass to begin with, or just more constructors in a single ADT.
data MyObj = MO1 { a1 :: String, b1 :: Int }
| MO2 { a2 :: String, b2 :: Int } deriving (Show,Read)
... for example.

Resources