I'm trying to use the Basics.toString function:
type Foo = Bar | Baz
main = text (toString Bar)
which, according to the Basics documentation, should be imported by default, but I'm getting a compile error:
I cannot find a `toString` variable:
13| main = text (toString Bar)
What am I missing?
Basics.toString was removed in version 0.19:
You'll need to use one of Debug.toString, String.fromInt or String.fromFloat, depending on the type of Bar.
Related
I'm currently taking calsses in F#, we have gotten the following assigment https://i.stack.imgur.com/Z4Hmy.png
And I'm currently just focusing on getting isEmpty to work, but it not that easy :D
I have tried to write the following in 'intLinked.fs':
module IntLinkedList
type intLinkedList = Nil | Cons of int * intLinkedList
//Check if a stack is empty
let isEmpty (stck: intLinkedList): bool = stck.IsEmpty
I'm certain that I have written my app.fsproj correct, but when I run the following debug message apears:
error FS0039: The type 'intLinkedList' does not define the field,
constructor or member 'IsEmpty'
The code works when:
I write the following in intLinkedList.fsi:
module IntLinkedList
type stack = int list
val isEmpty : stack -> bool
I write the following in intLinkedList.fs:
module IntLinkedList
type stack = int list
let isEmpty (stck: stack): bool = stck.IsEmpty
I write the following in intLinkedApp.fsx:
open IntLinkedList
let emptyList = []
isEmpty emptyList |> printfn " Empty list is empty : %A"
It's when I try to use the type intLinkedList I run into problems.
As far as I understand Nil is just an empty list [], but it doesn't seem to act like it.
Is it posible that any of you might be able to give me a hint, so I can get back on track?
Thanks in advance
Nil is not "just an empty list". Your type intLinkedList is a completely new type, not related to F# built-in list at all.
It has the same general structure as F# built-in list. In smartypants talk you might say it's "isomorphic" to the F# built-in list. But it's not the same thing.
This means that you can't use methods and functions that work with F# built-in lists on your custom type. You have to implement them yourself.
For example, the IsEmpty property might be implemented something like:
type intLinkedList = Nil | Cons of int * intLinkedList
with
member this.IsEmpty = match this with Nil -> true | Cons _ -> false
I suspect that this behavior may not be unique to F#, but I'll pick on it since that's what I'm using for work.
suppose I have a module
open System
module Bar =
let bar =
Console.WriteLine("BAR!")
"bar"
and I have the following in an fsx:
// this is a standard library function (Operators.defaultArg or Option.defaultValue)
let getValueOr v = function
| Some x -> x
| None -> v
let opt = Some "foo"
Console.WriteLine( opt |> getValueOr Bar.bar )
When I run this, I see the following printed
BAR!
foo
which is expected, since arguments are usually evaluated before the function body so I expect the effects in Bar.bar to be happen before getValueOr partially applies it (or even when the module is read).
However, when I compile the Bar module into a DLL and #r it, I see just
foo
In other words, Bar.bar doesn't get evaluated... why? Is it because of #r?
This behavior is actually desirable for something I'm trying to create, but it's a little counterintuitive and I'd like to understand it better.
This happens because of optimizations.
When you run in FSI, optimizations are turned off, so everything works the way you expect it to work.
But when you compile in Release (i.e. with optimizations), F# compiler is able to do a lot more because it knows the structure of your code. In this case, the function getValueOr gets inlined at call site, and your last line turns into roughly the following:
// C# syntax
Console.WriteLine( foo == null ? Bar.bar : foo.Value )
Here's another interesting experiment: if you move the definition of the Bar module to the same place where Bar.bar is referenced, the effect will (probably) reappear, because the definition of bar itself will be inlined, roughly like this:
// C# syntax:
Console.WriteLine( "BAR!" )
var bar = "bar"
var foo = new Some("foo")
Console.WriteLine( foo == null ? bar : foo.Value )
The bottom line is this: uncontrolled effects are bad. They make your program unpredictable. Try to avoid them.
I have a following piece of Elm code (getProjectView function is omitted for brievity):
type Model = Maybe List Project
model : Model
model = Nothing
getView : Model -> Html any
getView model =
case model of
Just projects ->
ul [] (List.map getProjectView projects)
Nothing -> p [] [ text "Still loading..." ]
When I try to compile the following snippet, the compiler fails with the following error:
-- TYPE MISMATCH --------- E:\dev\irrelephant-code\client\elm\Views\Projects.elm
Tag `Maybe.Just` is causing problems in this pattern match.
32| Just projects ->
^^^^^^^^^^^^^
The pattern matches things of type:
Maybe a
But the values it will actually be trying to match are:
Model
Indicating that compiler can't deduce that this Nothing is a value of type Model (which in turn is an alias of type Maybe List Project).
What am I doing wrong here? Is there a way to explicitly mark this Nothing as a value of the Model type?
I am using elm v0.18.0
You want to define model as a type alias of Maybe (List Product). Right now, with the type keyword, you are defining a new union/tag type with one value, Maybe, which expects to arguments, of type List and Product.
A working example is https://ellie-app.com/3MhPcgGzXqRa1/0
Any IDE wizards hanging out?
I want to do something seemingly simple, which is turning out to be fairly difficult: I want to replace all variable declarations of one type with variable declarations of another type
Ex:
Foo x; ==> Bar x;
protected final Foo x; ==> protected final Bar x;
public abstract Foo = Foo() + 7; ==> public abstract Bar = Foo() + 7;
I figure that this must be possible but I cannot, for the life of me, figure out how. I can get close, but I stall on the following issues:
How can I either not modify the "modifiers" like public, final, and so on, preceding the Foo variable declaration, or capture them so that I can make sure they don't get lost?
How can I not replace the right-hand side of the equals sign in the 3rd example?
Structural Search & Replace should work.
Search Pattern:
Foo $a$ = $b$;
Replacement Pattern:
Bar $a$ = $b$;
Click Edit Variables and set the Minimum count of b to 0 and Maximum count to 1. Modifiers should get saved automatically.
I'm curious to understand why this error happens and which is the best way to get around it.
I have a couple of files types.ml and types.mli which define a variant type value that can be of many different builtin OCaml types (float, int, list, map, set, etc..).
Since I have to use the std-lib over this variant type I needed to concretize the Set module through the functor to be able to use sets of value type by defining the ValueSet module.
The final .ml file is something like:
module rec I :
sig
type value =
Nil
| Int of int
| Float of float
| Complex of Complex.t
| String of string
| List of (value list) ref
| Array of value array
| Map of (value, value) Hashtbl.t
| Set of ValueSet.t ref
| Stack of value Stack.t
...
type t = value
val compare : t -> t -> int
end
= struct
(* same variant type *)
and string_value v =
match v with
(* other cases *)
| Set l -> sprintf "{%s} : set" (ValueSet.fold (fun i v -> v^(string_value i)^" ") !l "")
end
and OrderedValue :
sig
type t = I.value
val compare : t -> t -> int
end
= struct
type t = I.value
let compare = Pervasives.compare
end
and ValueSet : Set.S with type elt = I.value = Set.Make(I)
As you can see I had to define the ValueSet module from the functor to be able to use that datatype. The problem occurs when I want to use that module inside the declaration of I. So that I obtain the following error:
Error: Cannot safely evaluate the definition of the recursively-defined module I
Why does this happen? Which is a good way to solve it? And just to know, is my approach to what I'm trying to do correct? Apart from that it works as intended (I'm able to use the ValueSet type with my operations in other modules, but I have to comment the involved line in types.ml to pass compilation phase).
I tried to remove all the superfluous code and reduce the code to essential needed to investigate this error.. if it's not enought just ask :)
EDIT: according to OCaml reference we have that
Currently, the compiler requires that all dependency cycles between the recursively-defined module identifiers go through at least one “safe” module. A module is “safe” if all value definitions that it contains have function types typexpr1 -> typexpr2.
This is everything I found so far, but I don't get the exact meaning..
Thank in advance
After fixing the obvious errors, your example does compile (with OCaml 3.10, but I think this hasn't changed since recursive modules were introduced in 3.07). Hopefully my explanations below will help you find what, amongst the definitions you left out, caused your code to be rejected.
Here is some example code that is accepted:
module rec Value : sig
type t =
Nil
| Set of ValueSet.t
val compare : t -> t -> int
val nil : t
(*val f_empty : unit -> t*)
end
= struct
type t =
Nil
| Set of ValueSet.t
let compare = Pervasives.compare
let nil = Nil
(*let f_empty () = Set ValueSet.empty*)
end
and ValueSet : Set.S with type elt = Value.t = Set.Make(Value)
At the expression level, the module Value has no dependency on ValueSet. Therefore the compiler generates the code to initialize Value before the code to initialize Value, and all goes well.
Now try commenting out the definition of f_empty.
File "simple.ml", line 11, characters 2-200:
Cannot safely evaluate the definition of the recursively-defined module Value
Now Value does depend on ValueSet, and ValueSet always depends on Value because of the compare function. So they are mutually recursive, and the “safe module” condition must apply.
Currently, the compiler requires that all dependency cycles between the
recursively-defined module identifiers go through at least one "safe" module. A
module is "safe" if all value definitions that it contains have function types
typexpr_1 -> typexpr_2.
Here, ValueSet isn't safe because of ValueSet.empty, and Value isn't safe because of nil.
The reason to the “safe module” condition is the chosen implementation technique for recursive module:
Evaluation of a recursive module definition proceeds
by building initial values for the safe modules involved, binding all
(functional) values to fun _ -> raise Undefined_recursive_module. The defining
module expressions are then evaluated, and the initial values for the safe
modules are replaced by the values thus computed.
If you comment out the declaration of nil in the signature of Value, you can leave the definition and declaration of f_empty. That's because Value is now a safe module: it contains only functions. It's ok to leave the definition of nil in the implementation: the implementation of Value is not a safe module, but Value itself (which is its implementation coerced to a signature) is safe.
I'm really not sure what kind of syntax you're using in the signature that allows let ... I'm going to assume it was a mistake while reducing the code for us. You also don't need that OrderedType definition, possibly another fiddling error for us, since you don't use it in parameterisation of the Set module.
Aside from that, I have no problem running the following in the toplevel. Since this works pretty directly, I am unsure how you're getting that error.
module rec Value :
sig
type t =
| Nil
| Int of int
| Float of float
| String of string
| Set of ValueSet.t
val compare : t -> t -> int
val to_string : t -> string
end = struct
type t =
| Nil
| Int of int
| Float of float
| String of string
| Set of ValueSet.t
let compare = Pervasives.compare
let rec to_string = function
| Nil -> ""
| Int x -> string_of_int x
| Float x -> string_of_float x
| String x -> x
| Set l ->
Printf.sprintf "{%s} : set"
(ValueSet.fold (fun i v -> v^(to_string i)^" ") l "")
end
and ValueSet : Set.S with type elt = Value.t = Set.Make (Value)