This is prob an easy question but I just could not find the answer for this:
How can I access the parameters of a custom type?
Lets say my code is like this: (anotherFunc is only there to help me access the parameter)
data Shape = (Shape Color [Dimension])
func :: [Shape] -> [Shape]
func (x:xs) = anotherFunc x : func xs
anotherFunc :: [Shape] -> [Shape]
anotherFunc (Shape Color (x:xs)) = <some simple operations>
is there something similar to this??
func ( (Shape Color (x:xs)):shapes )
many thx!!
There is something very similar to that.
func ((Shape _ (x:xs)):shapes) = ...
However, your func just reimplements map, so you can use that and continue to use anotherFunc (which can be defined locally if you'd prefer):
func = map anotherFunc
where anotherFunc (Shape c ds) = ...
Related
I'm trying to pretty print a custom record type that contains a Hashtable (using the Base standard library) in OCaml with ppx-deriving, but I need to implement Hashtbl.pp for it to work.
I've tried looking at examples online and the best one that I found is https://github.com/ocaml-ppx/ppx_deriving#testing-plugins, but I'm still getting strange type errors like "This function has type Formatter.t -> (string, Value.t) Base.Hashtbl.t -> unit. It is applied to too many arguments; maybe you forgot a `;'"
How do you extend the Hashtbl module with a pp function?
Here is my code so far (Value.t is a custom type which I successfully annotated with [##deriving show]:
open Base
(* Extend Hashtbl with a custom pretty-printer *)
module Hashtbl = struct
include Hashtbl
let rec (pp : Formatter.t -> (string, Value.t) Hashtbl.t -> Ppx_deriving_runtime.unit) =
fun fmt -> function
| ht ->
List.iter
~f:(fun (str, value) ->
Caml.Format.fprintf fmt "#[<1>%s: %s#]#." str (Value.string_of value))
(Hashtbl.to_alist ht)
and show : (string, Value.t) Hashtbl.t -> Ppx_deriving_runtime.string =
fun s -> Caml.Format.asprintf "%a" pp s
;;
end
type t =
{ values : (string, Value.t) Hashtbl.t
; enclosing : t option
}
[##deriving show]
Solution 1
The type of the values field of your record is a parametrized with two type variables, therefore the deriver is trying to use a general pp function that is parametrized by the key and data pretty-printers, e.g., the following will enable show for any hashtable (with any key and any value, as long as keys and values are showable,
module Hashtbl = struct
include Base.Hashtbl
let pp pp_key pp_value ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%a: %a#]#." pp_key key pp_value data)
end
so you can finally define your type
type t = {
values : (string,Value.t) Hashtbl.t;
enclosing : t option;
} [##deriving show]
Solution 2 (recommended)
However, I would suggest another approach that instead of creating a general Hashtable module, creates a specialized Values module, e.g.,
module Values = struct
type t = (string, Value.t) Hashtbl.t
let pp ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%s: %s#]#." key (Value.to_string data))
end
Now you can use it as,
type t = {
values : Values.t;
enclosing : t option;
} [##deriving show]
Solution 3
If you still want a generic printable hash table, then I would advise against using the include statement, but, instead, implement just the required printable interface for the ('k,'s) Hashtbl.t type, e.g.,
module Hashtbl_printable = struct
type ('k,'s) t = ('k, 's) Hashtbl.t
let pp pp_key pp_value ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%a: %a#]#." pp_key key pp_value data)
end
type t = {
values : (string, Value.t) Hashtbl_printable.t;
enclosing : t option;
} [##deriving show]
I'm making a function readUntil that reads lines from user. Reading stops when f returns True for a line. Then the lines are returned as a list (the line that returned True is not included in that list). Here's what I have at the moment (some really raw/pseudo code now, excuse me):
readUntil :: (String -> Bool) -> IO [String]
readUntil f = fmap reverse (go []) where
go xs = do
x <- getLine
if f = True then return xs
else go (x : xs)
I would also like to make readUntil recursive (or implement a recursive helper function).
I've included a small example below. You're pretty much at the solution. The important bit is just remembering how you'd generate a non-monad recusive list, then just putting that in the monad.
collectUntil :: (Monad m) => m a -> (a -> Bool) -> m [a]
collectUntil act f = do
x <- act
if f x
then return []
else (x:) <$> collectUntil act f
readUntil :: (String -> Bool) -> IO [String]
readUntil = collectUntil getLine
I am trying to stick heterogeneous types in a list making use of flexible types
type IFilter<'a> =
abstract member Filter: 'a -> 'a
type Cap<'a when 'a: comparison> (cap) =
interface IFilter<'a> with
member this.Filter x =
if x < cap
then x
else cap
type Floor<'a when 'a: comparison> (floor) =
interface IFilter<'a> with
member this.Filter x =
if x > floor
then x
else floor
type Calculator<'a, 'b when 'b:> IFilter<'a>> (aFilter: 'b, operation: 'a -> 'a) =
member this.Calculate x =
let y = x |> operation
aFilter.Filter y
type TowerControl<'a> () =
let mutable calculationStack = List.empty
member this.addCalculation (x: Calculator<'a, #IFilter<'a>> ) =
let newList = x::calculationStack
calculationStack <- newList
let floor10 = Floor<int> 10
let calc1 = Calculator<int, Floor<int>> (floor10, ((+) 10))
let cap10 = Cap 10
let calc2 = Calculator (cap10, ((-) 5))
let tower = TowerControl<int> ()
tower.addCalculation calc1
tower.addCalculation calc2
In the example above
member this.addCalculation (x: Calculator<'a, #IFiler<'a>> ) =
produces the error
error FS0670: This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope.
Apologies if a similar question has already been posted.
Thank you.
There's no easy way to do this. It looks like you really want calculationStack to have type:
(∃('t:>IFilter<'a>).Calculator<'a, 't>) list
but F# doesn't provide existential types. You can use the "double-negation encoding" ∃'t.f<'t> = ∀'x.(∀'t.f<'t>->'x)->'x to come up with the following workaround:
// helper type representing ∀'t.Calculator<'t>->'x
type AnyCalc<'x,'a> = abstract Apply<'t when 't :> IFilter<'a>> : Calculator<'a,'t> -> 'x
// type representing ∃('t:>IFilter<'a>).Calculator<'a, 't>
type ExCalc<'a> = abstract Apply : AnyCalc<'x,'a> -> 'x
// packs a particular Calculator<'a,'t> into an ExCalc<'a>
let pack f = { new ExCalc<'a> with member this.Apply(i) = i.Apply f }
// all packing and unpacking hidden here
type TowerControl<'a> () =
let mutable calculationStack = List.empty
// note: type inferred correctly!
member this.addCalculation x =
let newList = (pack x)::calculationStack
calculationStack <- newList
// added this to show how to unpack the calculations for application
member this.SequenceCalculations (v:'a) =
calculationStack |> List.fold (fun v i -> i.Apply { new AnyCalc<_,_> with member this.Apply c = c.Calculate v }) v
// the remaining code is untouched
let floor10 = Floor<int> 10
let calc1 = Calculator<int, Floor<int>> (floor10, ((+) 10))
let cap10 = Cap 10
let calc2 = Calculator (cap10, ((-) 5))
let tower = TowerControl<int> ()
tower.addCalculation calc1
tower.addCalculation calc2
This has the big advantage that it works without modifying the Calculator<_,_> type, and that the semantics are exactly what you want, but the following disadvantages:
It's hard to follow if you're unfamiliar with this way of encoding existentials.
Even if you are familiar, there's a lot of ugly boilerplate (the two helper types) since F# doesn't allow anonymous universal qualification either. That is, even given that F# doesn't directly support existential types, it would be much easier to read if you could write something like:
type ExCalc<'a> = ∀'x.(∀('t:>IFilter<'a>).Calculator<'a,'t>->'x)->'x
let pack (c:Calculator<'a,'t>) : ExCalc<'a> = fun f -> f c
type TowerControl<'a>() =
...
member this.SequenceCalcualtions (v:'a) =
calculationStack |> List.fold (fun v i -> i (fun c -> c.Calculate v)) v
But instead we've got to come up with names for both helper types and their single methods. This ends up making the code hard to follow, even for someone already familiar with the general technique.
On the off chance that you own the Calculator<_,_> class, there's a much simpler solution that might work (it may also depend on the signatures of the methods of the real Calcuator<,> class, if it's more complex than what you've presented here): introduce an ICalculator<'a> interface, have Calculator<_,_> implement that, and make calculationStack a list of values of that interface type. This will be much more straightforward and easier for people to understand, but is only possible if you own Calculator<_,_> (or if there's already an existing interface you can piggy back on). You can even make the interface private, so that only your code is aware of its existence. Here's how that would look:
type private ICalculator<'a> = abstract Calculate : 'a -> 'a
type Calculator<'a, 'b when 'b:> IFilter<'a>> (aFilter: 'b, operation: 'a -> 'a) =
member this.Calculate x =
let y = x |> operation
aFilter.Filter y
interface ICalculator<'a> with
member this.Calculate x = this.Calculate x
type TowerControl<'a> () =
let mutable calculationStack = List.empty
member this.addCalculation (x: Calculator<'a, #IFilter<'a>> ) =
let newList = (x :> ICalculator<'a>)::calculationStack
calculationStack <- newList
member this.SequenceCalculations (v:'a) =
calculationStack |> List.fold (fun v c -> c.Calculate v) v
I have a function of type Csp -> Var -> Int -> Csp, and I want to apply this function to a list of [Var], just wondering if anyone can help me out I'm totally bamboozled!
From your comment, it sounds like you want a fold, for example:
foo :: Csp -> Var -> Int -> Csp -- your function
bar :: Csp -> [Var] -> Int -> Csp
bar c0 vs x = foldl (\c v -> foo c v x) c0 vs
Though it might be worth changing the order of the arguments a little to make it more suited for partial application:
foo :: Int -> Csp -> Var -> Csp
bar :: Int -> Csp -> [Var] -> Csp
bar x = foldl (foo x)
What you want is a fold. foldl has the signature foldl :: (a -> b -> a) -> a -> [b] -> a, so in your case you want a to be Csp h and b to be Var, giving you the type foldl :: (Csp -> Var -> Csp) -> Csp -> [Var] -> Csp. For the first argument you just pass it something like \csp var -> f csp var yourFixedInt where f is your function.
If you aren't familiar with folds what this does is apply, for each var in your list of Vars, the function you pass it (in this case just your function with the Int argument fixed) to a Csp accumulator and var.
(There are a lot better explanations of folds around, but I figured I'd include at least a short comment)
http://zvon.org/other/haskell/Outputprelude/map_f.html
This might be what you're looking for, no?
You want a fold, or so it sounds to me.
Suppose the function you have is f
f :: Csp -> Var -> Int -> Csp
vars = [ ..... ] :: [Var]
i :: Int -- the constant int argument to f
foldl g vars where g c v = f c v i
I think you need a fold.
answer :: (Csp -> Var -> Int -> Csp) -> Csp -> [Var] -> Int -> Csp
answer f csp vs i = foldl (\csp' v -> f csp' v i) csp vs
map takes a function and applies it to a list of values.
So as a simple example, if I have a function f x = x + 5, and a list l = [1,2,3], then map f l will return [6,7,8]
Given f :: Csp -> Var -> Int -> Csp, and l :: [Var], you should write
map (\x -> f csp x int) l -- note that the variable names (like "csp") can be anything
which will have the type :: Csp -> Int -> Csp. In other words, it will return a list of functions.
Is it really true that OCaml doesn't have a function which converts from a list to a set?
If that is the case, is it possible to make a generic function list_to_set? I've tried to make a polymorphic set without luck.
Fundamental problem: Lists can contain elements of any types. Sets (assuming you mean the Set module of the standard library), in contrary, rely on a element comparison operation to remain balanced trees. You cannot hope to convert a t list to a set if you don't have a comparison operation on t.
Practical problem: the Set module of the standard library is functorized: it takes as input a module representing your element type and its comparison operation, and produces as output a module representing the set. Making this work with the simple parametric polymoprhism of lists is a bit sport.
To do this, the easiest way is to wrap your set_of_list function in a functor, so that it is itself parametrized by a comparison function.
module SetOfList (E : Set.OrderedType) = struct
module S = Set.Make(E)
let set_of_list li =
List.fold_left (fun set elem -> S.add elem set) S.empty li
end
You can then use for example with the String module, which provides a suitable compare function.
module SoL = SetOfList(String);;
SoL.S.cardinal (SoL.set_of_list ["foo"; "bar"; "baz"]);; (* returns 3 *)
It is also possible to use different implementation of sets which are non-functorized, such as Batteries and Extlib 'PSet' implementation (documentation). The functorized design is advised because it has better typing guarantees -- you can't mix sets of the same element type using different comparison operations.
NB: of course, if you already have a given set module, instantiated form the Set.Make functor, you don't need all this; but you conversion function won't be polymorphic. For example assume I have the StringSet module defined in my code:
module StringSet = Set.Make(String)
Then I can write stringset_of_list easily, using StringSet.add and StringSet.empty:
let stringset_of_list li =
List.fold_left (fun set elem -> StringSet.add elem set) StringSet.empty li
In case you're not familiar with folds, here is a direct, non tail-recursive recursive version:
let rec stringset_of_list = function
| [] -> StringSet.empty
| hd::tl -> StringSet.add hd (stringset_of_list tl)
Ocaml 3.12 has extensions (7,13 Explicit naming of type variables and 7,14 First-class modules) that make it possible to instantiate and pass around modules for polymorphic values.
In this example, the make_set function returns a Set module for a given comparison function and the build_demo function constructs a set given a module and a list of values:
let make_set (type a) compare =
let module Ord = struct
type t = a
let compare = compare
end
in (module Set.Make (Ord) : Set.S with type elt = a)
let build_demo (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = List.fold_right S.add xs S.empty in
Printf.printf "%b\n" (S.cardinal set = List.length xs)
let demo (type a) xs = build_demo (make_set compare) xs
let _ = begin demo ['a', 'b', 'c']; demo [1, 2, 3]; end
This doesn't fully solve the problem, though, because the compiler doesn't allow the return value to have a type that depends on the module argument:
let list_to_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
List.fold_right S.add xs S.empty
Error: This `let module' expression has type S.t
In this type, the locally bound module name S escapes its scope
A possible work-around is to return a collection of functions that operate on the hidden set value:
let list_to_add_mem_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = ref (List.fold_right S.add xs S.empty) in
let add x = set := S.add x !set in
let mem x = S.mem x !set in
(add, mem)
If you don't mind a very crude approach, you can use the polymorphic hash table interface. A hash table with an element type of unit is just a set.
# let set_of_list l =
let res = Hashtbl.create (List.length l)
in let () = List.iter (fun x -> Hashtbl.add res x ()) l
in res;;
val set_of_list : 'a list -> ('a, unit) Hashtbl.t = <fun>
# let a = set_of_list [3;5;7];;
val a : (int, unit) Hashtbl.t = <abstr>
# let b = set_of_list ["yes";"no"];;
val b : (string, unit) Hashtbl.t = <abstr>
# Hashtbl.mem a 5;;
- : bool = true
# Hashtbl.mem a 6;;
- : bool = false
# Hashtbl.mem b "no";;
- : bool = true
If you just need to test membership, this might be good enough. If you wanted other set operations (like union and intersection) this isn't a very nice solution. And it's definitely not very elegant from a typing standpoint.
Just extend the original type, as shown in
http://www.ffconsultancy.com/ocaml/benefits/modules.html
for the List module:
module StringSet = Set.Make (* define basic type *)
(struct
type t = string
let compare = Pervasives.compare
end)
module StringSet = struct (* extend type with more operations *)
include StringSet
let of_list l =
List.fold_left
(fun s e -> StringSet.add e s)
StringSet.empty l
end;;
Using the core library you could do something like:
let list_to_set l =
List.fold l ~init:(Set.empty ~comparator:Comparator.Poly.comparator)
~f:Set.add |> Set.to_list
So for example:
list_to_set [4;6;3;6;3;4;3;8;2]
-> [2; 3; 4; 6; 8]
Or:
list_to_set ["d";"g";"d";"a"]
-> ["a"; "d"; "g"]