How can I create a function that only accepts a subset of constructors of a type? - idris

Let's say I have a type like this:
data Foo = Bar String | Baz | Qux String
I want to have a function like this:
get : Foo -> String
get (Bar s) = s
get (Qux s) = s
As written, this compiles, but it's not total, as there are missing cases; in other words, get Baz is treated like a hole rather than as an expression that doesn't typecheck.
I want to replace that Foo in the type signature of get with something that specifies that the value must be either a Bar or a Qux. How can I express this subset of the Foo type?

You could also mix the two approaches (by Kim Stiebel and Anton Trunov) and construct a helper data type. The type OnlyBarAndQux can only be constructed with values of Bar and Qux. For idris it is then possible to automatically infer a proof if this is the case when invoking get:
module FooMe
data Foo = Bar String | Baz | Qux String
data OnlyBarAndQux: Foo -> Type where
BarEy: OnlyBarAndQux (Bar s)
QuxEx: OnlyBarAndQux (Qux s)
||| get a string from a Bar or Qux
total
get: (f: Foo) -> {auto prf : OnlyBarAndQux f} -> String
get (Bar s) {prf = BarEy} = s
get (Qux s) {prf = QuxEx} = s
-- Tests
test1: get $ Bar "hello" = "hello"
test1 = Refl
test2: get $ Qux "hello" = "hello"
test2 = Refl
-- does not compile
-- test3: get $ Baz = "hello"

I'd follow the approach taken in the std library for List head, for example. This is basically what Markus wrote plus using Dec for witnessing that a Foo being not Baz is decidable:
%default total
data Foo = Bar String | Baz | Qux String
data NotBaz : Foo -> Type where
IsBar: NotBaz(Bar z)
IsQux: NotBaz(Qux z)
Uninhabited (NotBaz Baz) where
uninhabited _ impossible
notBaz : (f : Foo) -> Dec (NotBaz f)
notBaz Baz = No absurd
notBaz (Bar s) = Yes IsBar
notBaz (Qux s) = Yes IsQux
get: (f : Foo) -> {auto ok : NotBaz f} -> String
get (Bar s) { ok = IsBar } = s
get (Qux s) { ok = IsQux } = s
s: String
s = get (Bar "bar")
Some comments about this:
Do not use just a predicate a -> Bool for working with a subset type of a; create a view like NotBaz above. See the Idris tutorial on views, this post, and this answer for context.
Use Dec whenever possible instead of equality. Intutitively, you will be able to use Dec for predicates on types for which you can explicitly decide the truth of the predicate: see notBaz above.
auto implicit arguments can help reducing the visual/cognitive clutter at usage site

There is more than one way to do this, but the easiest is probably to make Foo a type constructor that takes a parameter indicating whether it's a Foo with a String in it or not. In this example I have used a Bool as the parameter:
%default total
data Foo : Bool -> Type where
Bar : String -> Foo True -- a Foo constructed with Bar will have type Foo True
Baz : Foo False -- and a Foo constructed with Baz will have type Foo False
Qux : String -> Foo True
get : Foo True -> String
get (Bar s) = s
get (Qux s) = s

I'd go with Kim Stebel's answer (if changing Foo is an option, as observed by #Eduardo Pareja Tobes), but I'd like to show another way. You can use a subset type, which is the same thing as dependent pair:
total
get : (f ** Not (f = Baz)) -> String
get (f ** pf) with (f)
get (f ** _) | (Bar s) = s -- this is as before
get (f ** contra) | Baz = void $ contra Refl -- a contradictory case
get (f ** _) | (Qux s) = s -- this is as before
(f ** Not (f = Baz)) can be translated as "some f of type Foo, but not Baz".
To call get you need to provide a dependent pair of an element of type Foo and a proof that it is not equal to Baz, like so:
s : String
s = get (Bar "bar" ** \Refl impossible)

Related

OCaml syntax error in functor

I'm trying to create a functor that makes a polynomial ring out of a ring. My underlying type, Ring_elt, has the following signature:
module type Ring_elt = sig
type t
val add : t -> t -> t
val mul : t -> t -> t
val zer : t
val one : t
val neg : t -> t
end;;
My polynomial functor looks like:
module Make_Poly2(Underlying:Ring_elt) = struct
type t = Poly of Underlying.t list
let rec create lst =
match List.rev lst with
| Underlying.zer :: tl -> create List.rev tl
| _ -> Poly of lst
end;;
(so the 'create' function should take a list, remove the leading zeros, and then return the polynomial of the result). However, I get a syntax error and utop underlines the "zer" after "Underlying."
By comparison, the following code (for making integer polynomials) works:
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| 0 :: tl -> create (List.rev tl)
| _ -> Poly lst
end;;
Any idea what's going on?
An OCaml pattern is built from constants, data constructors, and new names bound by the pattern match. Underlying.zer isn't any of those things. But 0 is one of them.
Seems like you can just use an if to compare against Underlying.zer.
Jeffrey's answer is good but instead of correcting it with an if construction, what you should do is the following : use algebraic data types
Instead of writing
val zer : t
val one : t
You could write
module type Ring_elt = sig
type t = Zer | One | Num of t
val add : t -> t -> t
val mul : t -> t -> t
val neg : t -> t
end
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| Underlying.Zer :: tl -> create (List.rev tl)
| _ -> Poly lst
end
It's a much better way of doing it since you can easily pattern match on it and even add some constants to your type t without problems.

Propositions vs. boolean values for input validation

I have the following code:
doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething
validate : String -> String
validate s = case (not (s == "")) of
False => s
True => doSomething s
After checking the input is not empty I would like to pass it to a function which accepts only validated input (not empty Strings).
As far as I understand the validation is taking place during runtime
but the types are calculated during compile time - thats way it doesn't work. Is there any workaround?
Also while playing with the code I noticed:
:t (("la" == "") == True)
"la" == "" == True : Bool
But
:t (("la" == "") = True)
"la" == "" = True : Type
Why the types are different?
This isn't about runtime vs. compile-time, since you are writing two branches in validate that take care, statically, of both the empty and the non-empty input cases; at runtime you merely choose between the two.
Your problem is Boolean blindness: if you have a value of type Bool, it is just that, a single bit that could have gone either way. This is what == gives you.
= on the other hand is for propositional equality: the only constructor of the type(-as-proposition) a = b is Refl : a = a, so by pattern-matching on a value of type a = b, you learn that a and b are truly equal.
I was able to get your example working by passing the non-equality as a proposition to doSomething:
doSomething : (s : String) -> Not (s = "") -> String
doSomething "" wtf = void $ wtf Refl
doSomething s nonEmpty = ?doSomething
validate : String -> String
validate "" = ""
validate s = doSomething s nonEmpty
where
nonEmpty : Not (s = "")
nonEmpty Refl impossible
As far as I understand the validation is taking place during runtime
but the types are calculated during compile time - thats way it
doesn't work.
That's not correct. It doesn't work because
We need the with form to perform dependent pattern matching, i. e. perform substitution and refinement on the context based on information gained from specific data constructors.
Even if we use with here, not (s == "") isn't anywhere in the context when we do the pattern match, therefore there's nothing to rewrite (in the context), and we can't demonstrate the not (s == "") = True equality later when we'd like to call doSomething.
We can use a wrapper data type here that lets us save a proof that a specific pattern equals the original expression we matched on:
doSomething : (s : String) -> (not (s == "") = True) -> String
doSomething s = ?doSomething
data Inspect : a -> Type where
Match : {A : Type} -> {x : A} -> (y : A) -> x = y -> Inspect x
inspect : {A : Type} -> (x : A) -> Inspect x
inspect x = Match x Refl
validate : String -> String
validate s with (inspect (not (s == "")))
| Match True p = doSomething s p
| Match False p = s

How a reexport a type in OCaml?

Let's say I have a module A which is defined as such:
type foo = Bar | Baz
a module B:
open A
let string_of_foo = function
| Bar -> "bar"
| Baz -> "baz"
and a module C:
open A
open B
let () =
let f = Bar in
print_endline (string_of_foo f)
How can I change the module B to reexport the type foo so that I don't have te open the module A in the module C?
Thanks.
One easy way to re-export things in B is to include A in B:
(* b.ml *)
include A
let string_of_foo = function
| Bar -> "bar"
| Baz -> "baz"
By compiling this b.ml with ocamlc -c -i b.ml, you can see what is happening:
type foo = A.foo = Bar | Baz
val string_of_foo : foo -> string
The signature of type foo in b.ml, type foo = A.foo = Bar | Baz may confuse you since it is not very often seen in OCaml. It indicates that the type B.foo is not only having the constructors of the same names but also completely equivalent with A.foo.
Another way to reexport A.foo from B is to use this type definition:
(* b.ml *)
type foo = A.foo = Bar | Baz
let string_of_foo = function
| Bar -> "bar"
| Baz -> "baz"
This is useful when you want to reexpose only some of types defined in a module. (include A reexports everything defined in A.)
Do not forget writing = A.foo, otherwise B.foo becomes a different type from A.foo even though it has the same names.
With one of these changes, you can write C without referring A directly:
open B
let () =
let f = Bar in
print_endline (string_of_foo f)
I'm just learning OCaml for 3 months for now so my answer may not be the best. But according to the book I started with: Real World OCaml it's not a good idea to open lots of modules. I would use dot notation, in your case:
a module B:
let string_of_foo = function
| A.Bar -> "bar"
| A.Baz -> "baz"
actually, only first A. is required to tell OCaml what type you have in mind. This one should work too:
let string_of_foo = function
| A.Bar -> "bar"
| Baz -> "baz"
But I prefer to be consistent.
and a module C:
let () =
let f = A.Bar in
print_endline (B.string_of_foo f)

Unsolved metavariable for function that has no inhabited arguments

I am getting an unsolved metavariable for foo in the code below:
namespace Funs
data Funs : Type -> Type where
Nil : Funs a
(::) : {b : Type} -> (a -> List b) -> Funs (List a) -> Funs (List a)
data FunPtr : Funs a -> Type -> Type where
here : FunPtr ((::) {b} _ bs) b
there : FunPtr bs b -> FunPtr (_ :: bs) b
total foo : FunPtr [] b -> Void
How do I convince Idris that foo has no valid patterns to match on?
I've tried adding
foo f = ?foo
and then doing a case split in Emacs on f (just to see what might come up), but that just removes the line, leaving foo as an unsolved meta.
It turns out all I need to do is enumerate all possible patterns for foo's argument, and then Idris is able to figure out, one by one, that they are un-unifyable with foo's type:
foo : FunPtr [] b -> Void
foo here impossible
foo (there _) impossible

How would I translate a Haskell type class into F#?

I'm trying to translate the Haskell core library's Arrows into F# (I think it's a good exercise to understanding Arrows and F# better, and I might be able to use them in a project I'm working on.) However, a direct translation isn't possible due to the difference in paradigms. Haskell uses type-classes to express this stuff, but I'm not sure what F# constructs best map the functionality of type-classes with the idioms of F#. I have a few thoughts, but figured it best to bring it up here and see what was considered to be the closest in functionality.
For the tl;dr crowd: How do I translate type-classes (a Haskell idiom) into F# idiomatic code?
For those accepting of my long explanation:
This code from the Haskell standard lib is an example of what I'm trying to translate:
class Category cat where
id :: cat a a
comp :: cat a b -> cat b c -> cat a c
class Category a => Arrow a where
arr :: (b -> c) -> a b c
first :: a b c -> a (b,d) (c,d)
instance Category (->) where
id f = f
instance Arrow (->) where
arr f = f
first f = f *** id
Attempt 1: Modules, Simple Types, Let Bindings
My first shot at this was to simply map things over directly using Modules for organization, like:
type Arrow<'a,'b> = Arrow of ('a -> 'b)
let arr f = Arrow f
let first f = //some code that does the first op
That works, but it loses out on polymorphism, since I don't implement Categories and can't easily implement more specialized Arrows.
Attempt 1a: Refining using Signatures and types
One way to correct some issues with Attempt 1 is to use a .fsi file to define the methods (so the types enforce easier) and to use some simple type tweaks to specialize.
type ListArrow<'a,'b> = Arrow<['a],['b]>
//or
type ListArrow<'a,'b> = LA of Arrow<['a],['b]>
But the fsi file can't be reused (to enforce the types of the let bound functions) for other implementations, and the type renaming/encapsulating stuff is tricky.
Attempt 2: Object models and interfaces
Rationalizing that F# is built to be OO also, maybe a type hierarchy is the right way to do this.
type IArrow<'a,'b> =
abstract member comp : IArrow<'b,'c> -> IArrow<'a,'c>
type Arrow<'a,'b>(func:'a->'b) =
interface IArrow<'a,'b> with
member this.comp = //fun code involving "Arrow (fun x-> workOn x) :> IArrow"
Aside from how much of a pain it can be to get what should be static methods (like comp and other operators) to act like instance methods, there's also the need to explicitly upcast the results. I'm also not sure that this methodology is still capturing the full expressiveness of type-class polymorphism. It also makes it hard to use things that MUST be static methods.
Attempt 2a: Refining using type extensions
So one more potential refinement is to declare the interfaces as bare as possible, then use extension methods to add functionality to all implementing types.
type IArrow<'a,'b> with
static member (&&&) f = //code to do the fanout operation
Ah, but this locks me into using one method for all types of IArrow. If I wanted a slightly different (&&&) for ListArrows, what can I do? I haven't tried this method yet, but I would guess I can shadow the (&&&), or at least provide a more specialized version, but I feel like I can't enforce the use of the correct variant.
Help me
So what am I supposed to do here? I feel like OO should be powerful enough to replace type-classes, but I can't seem to figure out how to make that happen in F#. Were any of my attempts close? Are any of them "as good as it gets" and that'll have to be good enough?
My brief answer is:
OO is not powerful enough to replace type classes.
The most straightforward translation is to pass a dictionary of operations, as in one typical typeclass implementation. That is if typeclass Foo defines three methods, then define a class/record type named Foo, and then change functions of
Foo a => yadda -> yadda -> yadda
to functions like
Foo -> yadda -> yadda -> yadda
and at each call site you know the concrete 'instance' to pass based on the type at the call-site.
Here's a short example of what I mean:
// typeclass
type Showable<'a> = { show : 'a -> unit; showPretty : 'a -> unit } //'
// instances
let IntShowable =
{ show = printfn "%d"; showPretty = (fun i -> printfn "pretty %d" i) }
let StringShowable =
{ show = printfn "%s"; showPretty = (fun s -> printfn "<<%s>>" s) }
// function using typeclass constraint
// Showable a => [a] -> ()
let ShowAllPretty (s:Showable<'a>) l = //'
l |> List.iter s.showPretty
// callsites
ShowAllPretty IntShowable [1;2;3]
ShowAllPretty StringShowable ["foo";"bar"]
See also
https://web.archive.org/web/20081017141728/http://blog.matthewdoig.com/?p=112
Here's the approach I use to simulate Typeclasses (from http://code.google.com/p/fsharp-typeclasses/ ).
In your case, for Arrows could be something like this:
let inline i2 (a:^a,b:^b ) =
((^a or ^b ) : (static member instance: ^a* ^b -> _) (a,b ))
let inline i3 (a:^a,b:^b,c:^c) =
((^a or ^b or ^c) : (static member instance: ^a* ^b* ^c -> _) (a,b,c))
type T = T with
static member inline instance (a:'a ) =
fun x -> i2(a , Unchecked.defaultof<'r>) x :'r
static member inline instance (a:'a, b:'b) =
fun x -> i3(a, b, Unchecked.defaultof<'r>) x :'r
type Return = Return with
static member instance (_Monad:Return, _:option<'a>) = fun x -> Some x
static member instance (_Monad:Return, _:list<'a> ) = fun x -> [x]
static member instance (_Monad:Return, _: 'r -> 'a ) = fun x _ -> x
let inline return' x = T.instance Return x
type Bind = Bind with
static member instance (_Monad:Bind, x:option<_>, _:option<'b>) = fun f ->
Option.bind f x
static member instance (_Monad:Bind, x:list<_> , _:list<'b> ) = fun f ->
List.collect f x
static member instance (_Monad:Bind, f:'r->'a, _:'r->'b) = fun k r -> k (f r) r
let inline (>>=) x (f:_->'R) : 'R = T.instance (Bind, x) f
let inline (>=>) f g x = f x >>= g
type Kleisli<'a, 'm> = Kleisli of ('a -> 'm)
let runKleisli (Kleisli f) = f
type Id = Id with
static member instance (_Category:Id, _: 'r -> 'r ) = fun () -> id
static member inline instance (_Category:Id, _:Kleisli<'a,'b>) = fun () ->
Kleisli return'
let inline id'() = T.instance Id ()
type Comp = Comp with
static member instance (_Category:Comp, f, _) = (<<) f
static member inline instance (_Category:Comp, Kleisli f, _) =
fun (Kleisli g) -> Kleisli (g >=> f)
let inline (<<<) f g = T.instance (Comp, f) g
let inline (>>>) g f = T.instance (Comp, f) g
type Arr = Arr with
static member instance (_Arrow:Arr, _: _ -> _) = fun (f:_->_) -> f
static member inline instance (_Arrow:Arr, _:Kleisli<_,_>) =
fun f -> Kleisli (return' <<< f)
let inline arr f = T.instance Arr f
type First = First with
static member instance (_Arrow:First, f, _: 'a -> 'b) =
fun () (x,y) -> (f x, y)
static member inline instance (_Arrow:First, Kleisli f, _:Kleisli<_,_>) =
fun () -> Kleisli (fun (b,d) -> f b >>= fun c -> return' (c,d))
let inline first f = T.instance (First, f) ()
let inline second f = let swap (x,y) = (y,x) in arr swap >>> first f >>> arr swap
let inline ( *** ) f g = first f >>> second g
let inline ( &&& ) f g = arr (fun b -> (b,b)) >>> f *** g
Usage:
> let f = Kleisli (fun y -> [y;y*2;y*3]) <<< Kleisli ( fun x -> [ x + 3 ; x * 2 ] ) ;;
val f : Kleisli<int,int list> = Kleisli <fun:f#4-14>
> runKleisli f <| 5 ;;
val it : int list = [8; 16; 24; 10; 20; 30]
> (arr (fun y -> [y;y*2;y*3])) 3 ;;
val it : int list = [3; 6; 9]
> let (x:option<_>) = runKleisli (arr (fun y -> [y;y*2;y*3])) 2 ;;
val x : int list option = Some [2; 4; 6]
> ( (*) 100) *** ((+) 9) <| (5,10) ;;
val it : int * int = (500, 19)
> ( (*) 100) &&& ((+) 9) <| 5 ;;
val it : int * int = (500, 14)
> let x:List<_> = (runKleisli (id'())) 5 ;;
val x : List<int> = [5]
Note: use id'() instead of id
Update: you need F# 3.0 to compile this code, otherwise here's the F# 2.0 version.
And here's a detailed explanation of this technique which is type-safe, extensible and as you can see works even with some Higher Kind Typeclasses.