In the ensemble.mli file I have
type 'a t;;
val ajouter : 'a -> 'a t -> 'a t
And in the ensemble.ml file:
type 'a t='a list
let rec ajouter =function a -> function
[] ->[a]
|h::t -> if h=a then h::t else h::(ajouter a t)
After compilation:
ocamlc ensemble.mli ensemble.ml
#load "ensemble.cmo"
Ensemble.ajouter 1 [];;
**Error: This expression has type 'a list but an expression
was expected of type int Ensemble.t**
I have to be able to give a detailed explanation about this error but I don't know exactly how to even fix it.So I really need your help.
Your type t is abstract. So nothing that comes from outside the Ensemble module can have that type. Thus, [] doesn't have the type 'a Ensemble.t as you would wish.
The usual solution is to export a value named (say) empty (or vide) from the module.
Related
Background: I am trying to expand my existing logging framework, which is currently a wrapper of static non-thread-safe methods over printfn and friends. My design goals are: having a generic interface ILog and concrete classes like Dbg, Log, Trace. I cannot use modules and functions, unfortunately, because I like to leverage the ConditionalAttribute on the methods.
I have a working approach that looks something like this:
type ILog<'T, 'U, 'V> =
abstract member log: 'T -> unit
abstract member log: 'U * 'V -> unit
type Dbg<'T, 'U, 'V when 'T :> Printf.StringFormat<string> and 'U :> Printf.StringFormat<'V -> string>>() =
static member inline _do_other_stuff() = "other stuff"
static member inline private _helper() =
printfn "%s %s" (Dbg<_,_,_>._do_other_stuff())
interface ILog<'T, 'U, 'V> with
[<Conditional("DEBUG")>] // removed from call site
member this.log(msg) = sprintf msg |> Dbg<_,_,_>._helper()
[<Conditional("DEBUG")>] // removed from call site
member this.log(fmt, a) = sprintf fmt a |> Dbg<_,_,_>._helper()
module TestMe =
let test() =
let dbg = new Dbg<_,_,_>() :> ILog<_,_,_>
dbg.log("test%i", 2)
Here, the compiler and syntax checker and coloring detects properly the dbg.log("test%i", 2) line, which is exactly what I want. It will also properly raise an error if I were to write "test%s" instead.
Now, if I take the above approach and expand it to create more overloads of the ILog.log method, this gets pretty hairy pretty quickly because of all the type annotations and the required use of syntax like Dbg<_,_,_>. Some of it can be hidden away, but still I figured there must be a better way.
One approach I tried, which seemed very FSharpish is:
type ILog =
abstract member log: _ -> unit
abstract member log: _ * _ -> unit
This compiles the interface and infers the type to be 'a0 and 'a0 -> 'a1 respectively (which seems wrong, why is the second log member getting the same 'a0?). But, I can't find any way of implementing such overly generic interface:
type Dbg() =
interface ILog with
member this.log v = v + 1 |> ignore // it won't infer int here
It raises:
The declared type parameter '?' cannot be used here, since the type parameter cannot be resolved at compile time.
Does F# 4.0 have a way of declaring interfaces in a more generic way, or am I stuck to having to declare them specifically (while this works, it is tedious).
I get the following error message:
"failure in proveterminate Error: Partial application of function convert_btree_to_tree in its body is not allowed while using Function"
from the following piece of Coq script, but I have no idea what is wrong. Can anyone give me some advice?
Function convert_btree_to_tree (t: btree (non_terminal' non_terminal terminal) terminal) {measure (fun t => bheight _ _ t)}:
tree (non_terminal' non_terminal terminal) terminal:=
let tl:= decompose t in
let ttl:= map convert_btree_to_tree tl in
let ttl':= convert_list_tree_to_tree_list ttl in
match broot _ _ t with
| inl n => node _ _ n ttl'
| inr t => node_t _ _ t
end.
Documentation on Function is very limited in the Reference Manual, does anybody know of a more complete and detailed reference, if possible with comments and examples?
I don't know much about Function but in your match, you return a node and a node_t. Since you didn't give the definitions, I don't know if these two constructors are from the same type, but I think you have a typo and the second case should return node t _ _ t.
EDIT after feedback from Marcus:
node_t is a constructor of tree which signature is terminal -> tree: given a term foo of type terminal, node_t foo is of type tree. node has the signature non_terminal -> tree_list -> tree.
Do you have any implicit parameters declared ? Otherwise, in your match cases, you apply too many arguments to node and node_t, which might be interpreted as partial application.
I have this problem and i do not understand where it came from.
Code:
class applicationFrameworksManager =
object(this)
val mutable frameworks = []
method add_framework name = ()(* if not (List.mem name frameworks) then frameworks <- List.append frameworks [name]; *)
method get_frameworks = frameworks
end;;
And the error:
Error: Some type variables are unbound in this type:
class applicationFrameworksManager :
object
val mutable frameworks : 'a list
method add_framework : 'b -> unit
method get_frameworks : 'a list
end
The method add_framework has type 'b -> unit where 'b is unbound
make: * [genobjc.cmx] Error 2
Can anybody help? To what can i bound it? Thanks. I'll add to this class a lot of strings and i want to get at the end only the unique ones.
The type of [] is polymorphic, hence its type 'a list contains an unbound type variable. The simple fix if you just want to add strings is to declare the type:
val mutable frameworks : string list = []
Your class as it stands is polymorphic; i.e., it could be used to manage lists of anything. You can do this by explicitly giving the class a type parameter for the type of the managed elements. But it sounds like you don't need that.
I try quite a while now to wrap my head around how to use validation in a digestive functors form field, that requires access to another monad. To cut it short I have a digestive form like this
studentRegistrationForm :: Monad m => Form Text m StudentRegistrationData
studentRegistrationForm = StudentRegistrationData
<$> "school" .: choice schools Nothing
<*> "studentId" .: check studentIdErrMsg (not . T.null) (text Nothing)
<*> "firstName" .: check firstNameErrMsg (not . T.null) (text Nothing)
<*> "lastName" .: check lastNameErrMsg (not . T.null) (text Nothing)
<*> "email" .: check emailErrMsg (E.isValid . T.unpack) (text Nothing)
(studentId is basically the username)
and would like to use the function usernameExists of Snap.Snaplet.Auth to check if the entered username is unique.
Just for completeness, here is the corresponding data type:
data StudentRegistrationData = StudentRegistrationData
{ school :: School -- ^ school the student is enroled
, studentId :: Text -- ^ matriculation number of the student
, firstName :: Text -- ^ first name of the student
, lastName :: Text -- ^ last name of the student
, email :: Text -- ^ email for sending password
} deriving (Show)
I create my form in a handler like:
studentRegistrationHandler :: AppHandler ()
studentRegistrationHandler = do
(view, registrationData) <- runForm "form" SRF.studentRegistrationForm
maybe (showForm "registration" view) createUser registrationData
showForm :: String -> View Text -> AppHandler ()
showForm name view =
heistLocal (bindDigestiveSplices view) $ render template
where
template = BS.pack $ "student-" ++ name ++ "-form"
So the problem I have now is to understand how to access the state of the Auth snaplet inside the form. Is it passed already or do I have to passed it myself? Would the functions checkM respectively validateM in the Text.Digestive.Form help me there?
I have found several examples of how to use digestive functors and snap auth and session, like:
snap example
digestive functors tutorial
postgres example
Getting started with Snap-Auth
But none shows Snap.Snaplet.Auth and digestive functors working together directly, and I am still such a noob when it comes to monad transformers and lifting... maybe it is too easy for me to see. :(
I can upload a standalone example on github, which shows my problem if it helps to illustrate it. Any hints, pointers and suggestions are very welcome! :)
Hannes
add on: I created an example application demonstrating basic authentication functionality, you may have a look here: digestive-functors-snap-auth-example enjoy!
I haven't tried this out to see if everything type checks, but here's the general idea. You are correct that you want to use either checkM or validateM to do your monadic validation. The type signature for checkM is informative:
checkM :: Monad m => v -> (a -> m Bool) -> Form v m a -> Form v m a
This tells us that the validation function will need to have the type (a -> m Bool) and the m must be the same as the m in the form. This means that you need to change the type of your form to something like this:
studentRegistrationForm :: Form Text AppHandler StudentRegistrationData
Now let's write the validator. Since we plan on using the usernameExists function in our validator, we need to look at that type signature:
usernameExists :: Text -> Handler b (AuthManager b) Bool
This actually looks a lot like the (a -> m Bool) type signature that we need. In fact, it's an exact match because Handler b (AuthManager b) is a monad. But even though it matches the (a -> m Bool) pattern exactly doesn't mean we're done quite yet. When you run your form, you're in the AppHandler monad which is probably just a type alias for Handler App App where App is your application's top-level snaplet state type. So what we need to do is convert Handler b (AuthManager b) into Handler b b which will unify with Handler App App. The with function from the snaplet API is exactly what we need. This makes our validation function quite simple:
validUser :: Text -> Handler App App Bool
validUser = liftM not . with auth . usernameExists
With this, you can use checkM usernameErrMsg validUser just like you use check in the above code.
I am java programmer reading and learning haskell now. I am trying write a simple program to connect (and disconnect) to postgres database using HDBC postgres driver. For simplicity i don't have any other logic in it.
It is throwing a function type error. I indented the code correct and if I remove disconnect then it works with the defined type.
Can some one shed some light on what i am missing defining the type for this function? i would apriciate your help.
thanks!
sample code:
import Database.HDBC
import Database.HDBC.PostgreSQL
import Database.HaskellDB
import Database.HaskellDB.HDBC.PostgreSQL
tryConnect :: Int -> (Database -> IO Connection) -> ()
tryConnect id =
do
c <- postgresqlConnect [("host","dbhost"),("dbname","db1"),("user","user1"),("password","test")]
disconnect c
return ()
I am getting the following error from GHCi
Couldn't match expected type `(Database -> IO Connection) -> a'
against inferred type `IO ()'
In a stmt of a 'do' expression: disconnect c
In the expression:
do { c <- postgresqlConnect
[("host", "dbhost"), ("dbname", "db1"), ....];
disconnect c;
return () }
In the definition of `insrt':
insrt id
= do { c <- postgresqlConnect [("host", "dbhost"), ....];
disconnect c;
return () }
Failed, modules loaded: none.
The problem is that you haven't provided enough arguments to postgresqlConnect. Its type signature is [(String, String)] -> (Database -> m a) -> m a, but you've only provided the first argument. Giving postgresqlConnect its second argument should solve the problem, and you'll be able to change the type declaration back to Int -> IO ().
EDIT: The answer below is totally wrong. My bad.
Well, the type signature is tryConnect :: Int -> (Database -> IO Connection) -> (). Generally this would indicate that the function takes an Int and a (Database -> IO Connection) and returns (), but the only parameter you've supplied in the function definition is id. Therefore, you actually have a function that takes an Int and returns a new function with the type signature (Database -> IO Connection) -> ().
This would be fine, except that the body of the function does not match this signature. The do expression returns an IO () value rather than the expected function, so you get an error because the compiler got a different return value than expected.
So, to conclude, it seems there's a parameter in the type signature that you haven't used in the actual function. Either remove that function from the type signature, or change the function to be tryConnect id func = ... rather than tryConnect id = ....