In a Haskell script, how does one programatically obtain the type signature of a function? - function

In Haskell (GHC), how can one obtain the type signature of the list of functions shown below?
[tail,init,reverse]
I unsuccessfully tried using the typeOf function of the Data.Typeable module. Specifically, I try to run the following Haskell script:
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show ( typeOf [tail,init,reverse] )) )
tests = TestList [ (TestLabel "myTest" myTest) ]
However, GHC responds with the following error:
C:\>ghci my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
my_script.hs:7:21: error:
* No instance for (Typeable a0) arising from a use of `typeOf'
* In the first argument of `show', namely
`(typeOf [tail, init, reverse])'
In the third argument of `assertEqual', namely
`(show (typeOf [tail, init, reverse]))'
In the first argument of `TestCase', namely
`(assertEqual
"\n\
\\n\
\Should have been \"[[a] -> [a]]\""
"[[a] -> [a]]"
(show (typeOf [tail, init, reverse])))'
Failed, modules loaded: none.
Prelude>
Update: The following HUnit test case isn't quite what I wanted, but I did get it to pass (based on David Young's suggestion). This test case at least forces the compiler to confirm that [tail,init,reverse] is of type [ [a] -> [a] ].
import Data.Typeable
import Test.HUnit
myTest = TestCase
( assertEqual "\n\nShould have been 3"
3
( length ( [tail,init,reverse] :: [[a]->[a]] ) ) )
tests = TestList [ (TestLabel "myTest" myTest) ]
C:\>my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( my_script.hs, interpreted )
Ok, modules loaded: Main.
*Main> runTestTT tests
Cases: 1 Tried: 1 Errors: 0 Failures: 0

You don't need a unit test to check a function's type. A unit tests runs after the code has been compiled, it's a dynamic test. However, type checking is a static test: all types are tested during the compilation of your program. Therefore, we can use GHC as a minimal static type checker and reduce your program to:
main :: IO ()
main = return ()
where
tailInitReverseAreListFunctions :: [[a] -> [a]]
tailInitReverseAreListFunctions = [tail, init, reverse]
You don't even need that test anymore the moment you actually test your functions with real data, because that application will (statically) test the function's type too.
Remember, Haskell is a statically typed language. The types are checked during compilation, before your code is run. Any type checking unit-test is therefore more or less a code-smell, because it can only pass.

Related

Racket: eval, namespace-attach-module vs. namespace-require

Let's say I have a module "foo.rkt" which exports a struct foo, e.g.,
#lang racket (provide foo) (struct foo ())
In another module, I use "foo.rkt" but I'd also like to associate the binding to "struct foo" to another namespace (I don't use prefabs for various reasons, so I can't use namespace-require).
I thought that I could use namespace-attach-module as follows:
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "foo.rkt" ns)
(eval '(foo) ns)
But that does not work, as namespace-mapped-symbols reveals that s is not bound in ns (if this is the only place to look for bindings). It does however work in the REPL. Why?
I assume the problem is to avoid instantiating the module in "foo.rkt" twice, since this leads to two incompatible structure definitions.
The function namespace-attach-module is part of the puzzle, but it only attaches
the instantiated module to the namespace ns - that is the name "foo.rkt" is now associated with the correct instantiation of "foo.rkt". It however doesn't make the bindings available in ns - that is the job of namespace-require.
Here is an example:
File: "computer.rkt"
#lang racket
(provide (struct-out computer))
(struct computer (name price) #:transparent)
File: "use-computer.rkt"
#lang racket
(require "computer.rkt") ; instatiate "computer.rkt"
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "computer.rkt" ns) ; ns now knows the same instance
(define a-computer
(parameterize ([current-namespace ns])
(namespace-require "computer.rkt")
(eval '(computer "Apple" 2000) ns)))
(computer-name a-computer) ; works, since ns used the same instantiation of "computer.rkt"
The result of running this is:
"Apple"
Note that removing the namespace-attach-module line leads to the error:
computer-name: contract violation;
given value instantiates a different structure type with the same name
expected: computer?
given: (computer "Apple" 2000)
since without the attachment, the namespace-require will instatiate "computer.rkt" a second time leading to two incompatible structures begin declared.

Can't define an exception only in a mli file

Ok, this is mostly about curiosity but I find it too strange.
Let's suppose I have this code
sig.mli
type t = A | B
main.ml
let f =
let open Sig in
function A | B -> ()
If I compile, everything will work.
Now, let's try to modify sig.mli
sig.mli
type t = A | B
exception Argh
and main.ml
main.ml
let f =
let open Sig in
function
| A -> ()
| B -> raise Argh
And let's try to compile it :
> ocamlc -o main sig.mli main.ml
File "main.ml", line 1:
Error: Error while linking main.cmo:
Reference to undefined global `Sig'
Well, is it just because I added the exception ? Maybe it means that exceptions are like functions or modules, you need a proper implementation.
But then, what if I write
main.ml
let f =
let open Sig in
function A | B -> ()
And try to compile ?
> ocamlc -o main sig.mli main.ml
>
It worked ! If I don't use the exception, it compiles !
There is no reason to this behaviour, right ? (I tested it on different compilers, 3.12.0, 4.00.0, 4.02.3 and 4.03.0 and all of them gave the same error)
Unlike variants, exception is not a pure type and requires its implementation in .ml file. Compile the following code with ocamlc -dlambda -c x.ml:
let x = Exit
-- the output --
(setglobal X!
(seq (opaque (global Pervasives!))
(let (x/1199 = (field 2 (global Pervasives!)))
(pseudo _none_(1)<ghost>:-1--1 (makeblock 0 x/1199)))))
You can see (let (x/1999 = (field 2 (global Pervasives!))).. which means assigning the value stored in the 2nd position of module Pervasives. This is the value of Exit. Exceptions have their values and therefore need .ml.
Variants do not require implementation. It is since their values can be constructed purely from their type information: constructors' tag integers. We cannot assign tag integers to exceptions (and their generalized version, open type constructors) since they are openly defined. Instead they define values for their identification in .ml.
To get an implementation of the exception, you need sig.ml. A .mli file is an interface file, a .ml file is an implementation file.
For this simple example you could just rename sig.mli to sig.ml:
$ cat sig.ml
type t = A | B
exception Argh
$ cat main.ml
let f =
let open Sig in
function
| A -> ()
| B -> raise Argh
$ ocamlc -o main sig.ml main.ml
I don't see a problem with this behavior, though it would be nice not to have to duplicate types and exceptions between .ml and .mli files. The current setup has the advantage of being simple and explicit. (I'm not a fan of compilers being too clever and doing things behind my back.)

couldn't match type 'ByteString o0 m0 Value' Vs 'ByteString Data.Void.Void IO Value'

I am trying the haskell-json-service. When I run the code, it throws error here:
app req sendResponse = handle (sendResponse . invalidJson) $ do
value <- sourceRequestBody req $$ sinkParser json
newValue <- liftIO $ modValue value
sendResponse $ responseLBS
status200
[("Content-Type", "application/json")]
$ encode newValue
Error is,
Couldn't match type ‘conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
ByteString o0 m0 Value’
with ‘conduit-1.2.4.1:Data.Conduit.Internal.Conduit.ConduitM
ByteString Data.Void.Void IO Value’
NB: ‘conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM’
is defined in ‘Data.Conduit.Internal.Conduit’
in package ‘conduit-1.2.4’
‘conduit-1.2.4.1:Data.Conduit.Internal.Conduit.ConduitM’
is defined in ‘Data.Conduit.Internal.Conduit’
in package ‘conduit-1.2.4.1’
Expected type: conduit-1.2.4.1:Data.Conduit.Internal.Conduit.Sink
ByteString IO Value
Actual type: conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
ByteString o0 m0 Value
In the second argument of ‘($$)’, namely ‘sinkParser json’
In a stmt of a 'do' block:
value <- sourceRequestBody req $$ sinkParser json
What does double dollar do? And what is this type - ByteString o0 m0 Value?
This appears to be the problem:
conduit-1.2.4:...
conduit-1.2.4.1:...
Your code is using a ByteString type from two different versions of the conduit library. From the point of view of GHC, these two types are unrelated: for instance, you can not pass the first type to a library function which expects the second one.
A cause for this could be using a library X which was compiled against the "old" conduit and a library Y which instead was compiled against the newer version. If your program imports X and Y, you will get in trouble when passing bytestrings from X to Y or vice versa. I have no idea about what X or Y actually are.
Maybe you can recompile X or Y so that they use the same version of conduit.

How print functions in Haskell like a python or scala?

I try to print functions in Haskell only for fun, like this example:
{-# LANGUAGE FlexibleInstances #-}
instance Show (Int -> Bool) where
show _ = "function: Int -> Bool"
loading in GHCi and run and example:
λ> :l foo
[1 of 1] Compiling Main ( foo.hs, interpreted )
foo.hs:2:1: Warning: Unrecognised pragma
Ok, modules loaded: Main.
λ> (==2) :: Int -> Bool
function: Int -> Bool
But, I wish to see that every function print yourself at invocation.
You can not have this for a general function as type information is present only at compile time, but you use Typeable class for writing something close enough if the type is an instance for Typeable class.
import Data.Typeable
instance (Typeable a, Typeable b) => Show (a -> b) where
show f = "Function: " ++ (show $ typeOf f)
Testing this in ghci
*Main> (+)
Function: Integer -> Integer -> Integer
*Main> (+10)
Function: Integer -> Integer
But this will not work for general functions until the type is restricted to a type that has Typeable instance.
*Main> zip
<interactive>:3:1:
Ambiguous type variable `a0' in the constraint:
(Typeable a0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
<interactive>:3:1:
Ambiguous type variable `b0' in the constraint:
(Typeable b0) arising from a use of `print'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of an interactive GHCi command: print it
*Main> zip :: [Int] -> [Bool] -> [(Int,Bool)]
Function: [Int] -> [Bool] -> [(Int,Bool)]
I'm assuming that you want the show method to print the function's address, which is what Python does:
>>> def foo(a):
... return a
...
>>> print foo
<function foo at 0xb76f679c>
There is really no supported way to do it (Haskell is a safe, high-level language that abstracts from such low-level details as function pointers), unless you're willing to use the internal GHC function unpackClosure#:
{-# LANGUAGE MagicHash,UnboxedTuples,FlexibleInstances #-}
module Main
where
import GHC.Base
import Text.Printf
instance Show (a -> a) where
show f = case unpackClosure# f of
(# a, _, _ #) -> let addr = (I# (addr2Int# a))
in printf "<function ??? at %x>" addr
main :: IO ()
main = print (\a -> a)
Testing:
$ ./Main
<function ??? at 804cf90>
Unfortunately, there is no way to get the function's name, since it is simply not present in the compiled executable (there may be debug information, but you can't count on its presence). If your function is callable from C, you can also get its address by using a C helper.

Interaction between optimizations and testing for error calls

I have a function in a module that looks something like this:
module MyLibrary (throwIfNegative) where
throwIfNegative :: Integral i => i -> String
throwIfNegative n | n < 0 = error "negative"
| otherwise = "no worries"
I could of course return Maybe String or some other variant, but I think it's fair to say that it's a programmer error to call this function with a negative number so using error is justified here.
Now, since I like having my test coverage at 100% I want to have a test case that checks this behavior. I have tried this
import Control.Exception
import Test.HUnit
import MyLibrary
case_negative =
handleJust errorCalls (const $ return ()) $ do
evaluate $ throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
main = runTestTT $ TestCase case_negative
and it sort of works, but it fails when compiling with optimizations:
$ ghc --make -O Test.hs
$ ./Test
### Failure:
must throw when given a negative number
Cases: 1 Tried: 1 Errors: 0 Failures: 1
I'm not sure what's happening here. It seems like despite my use of evaluate, the function does not get evaluated. Also, it works again if I do any of these steps:
Remove HUnit and call the code directly
Move throwIfNegative to the same module as the test case
Remove the type signature of throwIfNegative
I assume this is because it causes the optimizations to be applied differently. Any pointers?
Optimizations, strictness, and imprecise exceptions can be a bit tricky.
The easiest way to reproduce this problem above is with a NOINLINE on throwIfNegative (the function isn't being inlined across module boundaries either):
import Control.Exception
import Test.HUnit
throwIfNegative :: Int -> String
throwIfNegative n | n < 0 = error "negative"
| otherwise = "no worries"
{-# NOINLINE throwIfNegative #-}
case_negative =
handleJust errorCalls (const $ return ()) $ do
evaluate $ throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
main = runTestTT $ TestCase case_negative
Reading the core, with optimizations on, the GHC inlines evaluate properly (?):
catch#
# ()
# SomeException
(\ _ ->
case throwIfNegative (I# (-1)) of _ -> ...
and then floats out the call to throwIfError, outside of the case scrutinizer:
lvl_sJb :: String
lvl_sJb = throwIfNegative lvl_sJc
lvl_sJc = I# (-1)
throwIfNegative =
\ (n_adO :: Int) ->
case n_adO of _ { I# x_aBb ->
case <# x_aBb 0 of _ {
False -> lvl_sCw; True -> error lvl_sCy
and strangely, at this point, no other code now calls lvl_sJb, so the entire test becomes dead code, and is stripped out -- GHC has determined that it is unused!
Using seq instead of evaluate is happy enough:
case_negative =
handleJust errorCalls (const $ return ()) $ do
throwIfNegative (-1) `seq` assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
or a bang pattern:
case_negative =
handleJust errorCalls (const $ return ()) $ do
let !x = throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
so I think we should look at the semantics of evaluate:
-- | Forces its argument to be evaluated to weak head normal form when
-- the resultant 'IO' action is executed. It can be used to order
-- evaluation with respect to other 'IO' operations; its semantics are
-- given by
--
-- > evaluate x `seq` y ==> y
-- > evaluate x `catch` f ==> (return $! x) `catch` f
-- > evaluate x >>= f ==> (return $! x) >>= f
--
-- /Note:/ the first equation implies that #(evaluate x)# is /not/ the
-- same as #(return $! x)#. A correct definition is
--
-- > evaluate x = (return $! x) >>= return
--
evaluate :: a -> IO a
evaluate a = IO $ \s -> let !va = a in (# s, va #) -- NB. see #2273
That #2273 bug is a pretty interesting read.
I think GHC is doing something suspicious here, and recommend not using evalaute (instead, use seq directly). This needs more thinking about what GHC is doing with the strictness.
I've filed a bug report to help get a determination from GHC HQ.