I am a bit stumped by this error message
Warning: Error in module Chapter2:
Error in value declaration unionIsForeign:
Error checking that type
Control.Monad.Eff.Eff (trace :: Debug.Trace.Trace | u8717) u8715
subsumes type
Data.Either.Either Data.Foreign.ForeignError Chapter2.Union
Error at src/Chapter2.purs line 16, column 18 - line 20, column 1:
Cannot unify type
Control.Monad.Eff.Eff
with type
Data.Either.Either
that is the result of this code
module Chapter2 where
import Debug.Trace
import Data.Foreign
import Data.Foreign.Class
import Control.Monad.Eff
sideeffect :: forall e. Number -> Eff (trace :: Trace | e) Number
sideeffect v = return v
data Union = S String
instance unionIsForeign :: IsForeign Union where
read value = do
v <- sideeffect 42
return $ S "Test"
main = do
trace "Test"
Why is there a need to unify Eff and Either?
This seems to be only the case when instantiating a type class of IsForeign.
sideeffectruns happily in main- of course main has a signature that states its usage of the Eff Monad
> :t Chapter2.main
Compiling Chapter2
forall t20. Control.Monad.Eff.Eff (trace :: Debug.Trace.Trace | t20) Prelude.Unit
The key parts are:
from Data.Foreign.Class:
class IsForeign a where
read :: Foreign -> F a
and from Data.Foreign:
type F = Either ForeignError
So, your read function has a declared return type of Either ForeignError Union.
But since you're using sideeffect which has a return type of Eff (trace :: Trace | e) Number, in the do block, the inferred type of the do block is an Eff ... value.
That is, you're trying to return an Eff ... from something which has to return an Either ... and the compiler is complaining because it can't unify Eff ... with Either ....
Related
So I want to write a function that takes a first class module as an argument that works on Base.Map and Base.Hashtbl, but I'm running into a problem. This code illustrates what's going on:
module type Len_intf = sig
type t
val length : t -> int
end
let show (type a) (module L : Len_intf with type t = a) h =
printf "len: %d\n" ## L.length h
let test (type a) h =
show (module Hashtbl : Len_intf with type t = a) h
Attempting to compile this results in:
Error: Signature mismatch:
...
Type declarations do not match:
type ('a, 'b) t = ('a, 'b) Poly.t
is not included in
type t
They have different arities.
File "test.ml", line 2, characters 2-8:
Expected declaration
File "src/hashtbl_intf.ml", line 552, characters 2-17:
Actual declaration
Is this even possible, due to the different type arity of Hashtbl and Map?
Writing a function that takes a first-class module is certainly possible (you did so), and it can be called like that:
let test (type a) (type b) h =
let module M = struct
type t = (a,b) Hashtbl.t
let length = Hashtbl.length
end in
show (module M) h
But I do not think it is possible to do it the way you want. Indeed, type equalities come afterwards, in addition to what the signature already describes. They cannot prevent a type arity mismatch.
I just tried to write the simplest maybe function I could imagine in Haskell, and got this error message. And magically it only appears, when I try to evaluate myHead for an empty list. What did I do wrong?
module Main
where
myHead :: [a] -> Maybe a
myHead [] = Nothing
myHead (x:_) = Just x
main = do
print (myHead [])
When I run it from a file, I get this output :
main.hs:15:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
... plus 22 others
...plus 12 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of a 'do' block: print (myHead [])
In the expression: do { print (myHead []) }
In an equation for ‘main’: main = do { print (myHead []) }
<interactive>:3:1: error:
• Variable not in scope: main
• Perhaps you meant ‘min’ (imported from Prelude)
There's nothing wrong with myHead, you would have the same issue if you used:
main = do
print Nothing
The issue here is that Nothing and myHead [] have a polymorphic type Maybe a, for any a. Then, print is called to write that value. For that, print has to require that Maybe a is convertible to string: it does that by requiring Show (Maybe a), which in turn it requires Show a.
However, there is no universal instance of Show a: the compiler now needs to know what a is before it can convert that to string.
Note this
print (Just 3 :: Maybe Int) -- OK
print (Just id :: Maybe (Int->Int)) -- Not OK! Functions can not be printed
The solution is to use a concrete type for your code
main = do
print (myHead [] :: Maybe Int) -- or any other showable type
I want to write a sample function that takes a list of any type and returns the head element only if the list is a list of reals.
Otherwise, the function should give the error message
. . . E r r o r : operator and operand don ’ t . . .
datatype typeR = Real of real
fun head(xs) =
case xs of
[] => raise List.Empty |
Real (x::_) => x:real ;
It's not entirely clear what you're after – you can't write a function that takes "any type" and then examines the parameter type.
(Writing head(xs), without a type annotation, does not make head a function that takes any type. Its type is inferred.)
If you want a function typeR list -> real, your main mistake was writing Real (x::_) where you should have written (Real x) :: _.
That is,
fun head(xs) =
case xs of
[] => raise List.Empty
| (Real x)::_ => x
or, more idiomatically,
fun head [] = raise List.Empty
| head (Real x :: _) = x
(fn x:real list => hd x ) [ 4 ,5 ];
out> error: Type error in function application
(fn x:real list => hd x ) [ 4.0 ,5.0 ];
out> it = 4.0: real
First some feedback:
This function is prone to failure since it only accepts a margin of its possible input. Write total functions when you can.
raise Empty would not be descriptive of the situation where the list is non-empty but the first element doesn't contain a real. Another exception should be raised then.
The following requirement is highly suspicious.
Otherwise, the function should give the error message
. . . E r r o r : operator and operand don ’ t . . .
It suggests that you don't differentiate between run-time exceptions and compile-time errors. This is symptomatic for a programming experience with dynamically typed languages where errors and exceptions are all handled after the program is started.
Then some ideas:
Lists in Standard ML are homogeneous, which means they can only be of one type at a time determined in the type-checking phase of compilation. There are a few ways you can deal with that and achieve more dynamic typing;
Using algebraic data types [wiki.haskell.org]:
datatype dynamic = R of real
| I of int
| B of bool
| S of string
fun headR [] = raise Empty
| headR (R r :: _) = r
| headR _ = raise Domain
Then headR does not actually accept any type. It accepts exactly one, dynamic, that can hold any fixed amount of value constructors with parameters of arbitrary type. This mimics heterogeneous lists:
val foos = [R 42.0, I 10, B true, S "Hello, World!"]
Using exceptions [informallyabstract.blogspot.com]:
datatype dynamic = Dynamic of exn
exception IsReal of real
fun wrap_real r = Dynamic (IsReal r)
fun unwrap_real (Dynamic ex) = raise ex handle IsReal r => r
fun headR (d::_) = unwrap_real
| headR [] = raise Empty
Then headR likewise only accepts one type, dynamic, and fails with whatever exception that was used instead of the real wrapper. The difference between using exceptions and a regular datatype definition is that exceptions can be extended with new constructors later:
exception IsString of string
fun wrap_string r = Dynamic (IsString r)
fun unwrap_string (Dynamic ex) = raise ex handle IsString r => r
val foos = [wrap_real 42.0, wrap_string "This didn't exist before."]
Neither are preferable because they introduce an unnecessary risk of run-time failure.
I have a function PolyInterpretation (http://color.inria.fr/doc/CoLoR.PolyInt.APolyInt.html)
Definition PolyInterpretation := forall f : Sig, poly (arity f).
and a module signature TPolyInt(http://color.inria.fr/doc/CoLoR.PolyInt.APolyInt_MA.html)
Module Type TPolyInt.
Parameter sig : Signature.
Parameter trsInt : PolyInterpretation sig.
Parameter trsInt_wm : PolyWeakMonotone trsInt.
End TPolyInt.
Module PolyInt (Export PI : TPolyInt).
Then in my file rainbow.v, I define a module TPolyInt_imp purpose to use functor PolyInt
Module TPolyInt_imp.
Variable arity : symbol -> nat.
Variable l : list {g : symbol & poly (arity f).
Definition sig := Sig arity.
Definition trsInt f := fun_of_pairs_list f l.
...
End TPolyInt_imp.
Where fun_of_pairs_list has type: forall f: Cpf0.symbol, list {g : symbol & poly (arity g)} -> poly (arity f)
Then I define a module P:
Module Export P := PolyInt TPolyInt_imp.
The Coqproof assistant accepted the definition P above.
Then I used extraction to extract to OCaml.
I write it in another file: extraction.v
Extraction Language Ocaml.
Set Extraction Optimize.
Set Extraction AccessOpaque.
Separate Extraction rainbow.P.
It works fine.
Here is the code after the extraction
module TPolyInt_imp =
struct
(** val arity : symbol -> int **)
let arity =
failwith "AXIOM TO BE REALIZED"
(** val l : (symbol, poly) sigT list **)
let l =
failwith "AXIOM TO BE REALIZED"
(** val coq_sig : coq_Signature **)
let coq_sig =
coq_Sig arity
(** val trsInt : symbol -> poly **)
let trsInt f =
fun_of_pairs_list arity f l
end
module P = PolyInt(TPolyInt_imp)
Because inside the functor TPolyInt_imp they included Variable and generate the failwith AXIOMthen I decided to define a new signature to contain all those variables.
Module Type Arity.
Variable arity : symbol -> nat.
Variable l : list {g : symbol & poly (arity g)}.
End Arity.
Then define a new functor taking (Arity) as a parameter. And inside this functor I define module TPolyInt_imp (like TPolyInt_imp before).
Module S (Import A: Arity).
Module TPolyInt_imp.
Definition sig := Sig arity.
Definition trsInt f := fun_of_pairs_list f l.
...
End TPolyInt_imp.
Module P := PolyInt TPolyInt_imp.
End S.
Then I use the extraction to extract it to Ocaml.
Extraction Language Ocaml.
Set Extraction Optimize.
Set Extraction AccessOpaque.
Separate Extraction S.
Then I got an error saying that:
Error: Signature mismatch:
...
Values do not match:
val trsInt : Cpf0.symbol -> Polynom.poly
is not included in
val trsInt : APolyInt.coq_PolyInterpretation
File "rainbow.ml", line 534, characters 8-14: Actual declaration
The code after the extraction:
module type Arity =
sig
val arity : symbol -> int
val l : (symbol, poly) sigT list
end
module S =
functor (A:Arity) ->
struct
module TPolyInt_imp =
struct
(** val coq_sig : coq_Signature **)
let coq_sig =
coq_Sig A.arity
(** val trsInt : symbol -> poly **)
let trsInt f =
fun_of_pairs_list A.arity f A.l
end
module P = PolyInt(TPolyInt_imp)
What is wrong with the extraction? and the reason why they have this error? How can I correct my code that I can get the success compile after the extraction?
Also I do not want to define a new module that implement the signature Arity.
I am so sorry for my code lacking of type and not able to compile. I am trying to give the idea of my problem.
Let's say I have a list of options:
let opts = [Some 1; None; Some 4]
I'd like to convert these into an option of list, such that:
If the list contains None, the result is None
Otherwise, the various ints are collected.
It's relatively straightforward to write this for this specific case (using Core and the Monad module):
let sequence foo =
let open Option in
let open Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
However, as the question title suggests, I'd really like to abstract over the type constructor rather than specialising to Option. Core seems to use a functor to give the effect of a higher kinded type, but I'm not clear how I can write the function to be abstracted over the module. In Scala, I'd use an implicit context bound to require the availability of some Monad[M[_]]. I'm expecting that there's no way of implicitly passing in the module, but how would I do it explicitly? In other words, can I write something approximating this:
let sequence (module M : Monad.S) foo =
let open M in
let open M.Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
Is this something that can be done with first class modules?
Edit: Okay, so it didn't actually occur to me to try using that specific code, and it appears it's closer to working than I'd anticipated! Seems the syntax is in fact valid, but I get this result:
Error: This expression has type 'a M.t but an expression was expected of type 'a M.t
The type constructor M.t would escape its scope
The first part of the error seems confusing, since they match, so I'm guessing the problem is with the second - Is the problem here that the return type doesn't seem to be determined? I suppose it's dependent on the module which is passed in - is this a problem? Is there a way to fix this implementation?
First, here is a self-contained version of your code (using the legacy
List.fold_left of the standard library) for people that don't have
Core under hand and still want to try to compile your example.
module type MonadSig = sig
type 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val return : 'a -> 'a t
end
let sequence (module M : MonadSig) foo =
let open M in
let (>>=) = bind in
List.fold_left (fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) (return []) foo;;
The error message that you get means (the confusing first line can
be ignored) that the M.t definition is local to the M module, and
must not escape its scope, which it would do with what you're trying
to write.
This is because you are using first-class modules, that allow to
abstract on modules, but not to have dependent-looking types such as
the return type depends on the argument's module value, or at least
path (here M).
Consider this example:
module type Type = sig
type t
end
let identity (module T : Type) (x : T.t) = x
This is wrong. The error messages points on (x : T.t) and says:
Error: This pattern matches values of type T.t
but a pattern was expected which matches values of type T.t
The type constructor T.t would escape its scope
What you can do is abstract on the desired type before you abstract on the first-class module T, so that there is no escape anymore.
let identity (type a) (module T : Type with type t = a) (x : a) = x
This relies on the ability to explicitly abstract over the type variable a. Unfortunately, this feature has not been extended to abstraction over higher-kinded variables. You currently cannot write:
let sequence (type 'a m) (module M : MonadSig with 'a t = 'a m) (foo : 'a m list) =
...
The solution is to use a functor: instead of working at value level, you work at the module level, which has a richer kind language.
module MonadOps (M : MonadSig) = struct
open M
let (>>=) = bind
let sequence foo =
List.fold_left (fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) (return []) foo;;
end
Instead of having each monadic operation (sequence, map, etc.) abstract over the monad, you do a module-wide abstraction.