GithubHelp home page GithubHelp logo

antalsz / hs-to-coq Goto Github PK

View Code? Open in Web Editor NEW
280.0 280.0 27.0 12.1 MB

Convert Haskell source code to Coq source code

Home Page: https://hs-to-coq.readthedocs.io

License: MIT License

Coq 56.25% Haskell 37.69% Perl 0.06% Yacc 1.76% Makefile 3.54% Nix 0.14% Emacs Lisp 0.14% Ruby 0.34% C++ 0.10%

hs-to-coq's People

Contributors

abailly avatar antalsz avatar crizkallah avatar ericgiovannini avatar euisuny avatar hengchu avatar joscoh avatar jwiegley avatar lastland avatar liyishuai avatar lysxia avatar nomeata avatar samuelgruetter avatar sweirich avatar threonorm avatar trommler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hs-to-coq's Issues

Instances need to be sorted

Given this code (test case FTP.hs, names changed from their base version to avoid clashes)

instance Foltable Pair where
  foltMap f (Pair x y) = f x `mabbend` f y

instance Trafersable Pair where
  traferse f (Pair x y) = purr Pair <**> f x <**> f y

instance Momoid a => Momoid (Pair a) where
  mempti = Pair mempti mempti
  (Pair a b) `mabbend` (Pair c d) = Pair (a `mabbend` b) (c  `mabbend` d)

instance Abblicative Pair where
  purr x = Pair x x
  (Pair f1 f2) <**> (Pair x y) = Pair (f1 x) (f2 y)

instance Funktor Pair where
  fmaap f (Pair a b) = Pair (f a) (f b)

The output needs to put them into the right order. In doing so, it needs to take superclass constraints into account! Because of

class (Funktor t, Foltable t) => Trafersable t where
    traferse :: Abblicative f => (a -> f b) -> t a -> f (t b)

the Trafersable instance needs to come after the Foltable instance. This information is syntactically not very obvious.

An alternative to sorting might be parametrizing the instances, i.e. produce

Instance instance_Trafersable_Pair_24__ `{Funktor Pair} `{Foltable Pair} : !Trafersable Pair := {
  traferse := fun {a} {b} {f} `{Abblicative f} => traferse_29__ }.

instead of

Instance instance_Trafersable_Pair_24__ : Trafersable Pair := {
  traferse := fun {a} {b} {f} `{Abblicative f} => traferse_29__ }.

This defers the resolution of the superclass instances to when the instance is actually used.

-N flag includes skipped modules

When I convert GHC.Base using the -N flag, with the following skipped modules

skip module GHC.Arr
skip module GHC.Generics
skip module GHC.Types
skip module GHC.CString
skip module GHC.Classes
skip module GHC.Magic
skip module GHC.Err
skip module GHC.IO
skip module GHC.Integer
skip module GHC.Unicode

skip module GHC.Num
skip module GHC.Char
skip module GHC.Real
skip module Data.Either
skip module Data.Proxy
skip module GHC.Enum
skip module Data.Bits
skip module Data.Type.Equality
skip module GHC.Prim
skip module GHC.Tuple
skip module Control.Category
skip module Data.Functor.Const
skip module Data.IntMap
skip module Data.IntMap.Base
skip module Data.IntSet.Base

translation still fails on :~: which is from Data.Type.Equality.

Implement `skip method`

The normal skip is a bit to weak, because a skipped method needs to be skipped both in the class definition and the instance definition.

Format:

skip method Monad fail

The Monad is unqualified; this seemed to be the most convenient choice, given that this edit needs to be used both where a class is declared (and hence the name is unqualified) and where a class is referenced (where it can be qualified).

skip constructor

Need a skip to eliminate constructor from data type definitions and branches for that constructor from functions.

Cannot find class information for Foldable/Traversable/Monoid

When I translate ghc/compiler/Util/Pair.v (in examples/ghc)

I get these messages:

(* Translating `instance Data.Foldable.Foldable Pair' failed: OOPS! Cannot find
   information for class "Data.Foldable.Foldable" unsupported *)
 
(* Translating `instance Data.Traversable.Traversable Pair' failed: OOPS! Cannot
  find information for class "Data.Traversable.Traversable" unsupported *)

(* Translating `instance forall {a}, forall `{GHC.Base.Monoid a},
  GHC.Base.Monoid (Pair a)' failed: OOPS! Cannot find information for class
 "GHC.Base.Monoid" unsupported *)

Do we need to do something special to tell hs-to-coq where to find these classes?

Polymorphic type annotations

I have put a minimal example in examples/tests. In summary, if you have the following functions:

comp :: (b -> c) -> (a -> b) -> a -> c
comp f g x = f (g x)

id2 :: (a -> a) -> (a -> a) -> a -> a
id2 = comp :: (a -> a) -> (a -> a) -> a -> a

hs-to-coq will translate it to:

Definition comp {b} {c} {a} : (b -> c) -> (a -> b) -> a -> c :=
  fun f g x => f (g x).

Definition id2 {a} : (a -> a) -> (a -> a) -> a -> a :=
  comp : (forall {a}, (a -> a) -> (a -> a) -> a -> a).

Coq will complain that there is a type error:

Error:
In environment
a : Type
The term "comp" has type "(?b -> ?c) -> (?a -> ?b) -> ?a -> ?c"
while it is expected to have type
 "forall a : Type, (a -> a) -> (a -> a) -> a -> a".

Generate metadata/"interface" files

In order to support things such as correctly knowing data type constructors or default modules outside of base, or correctly extending skip method to modules that import a type class, we need to generate metadata files. Current plan:

  1. When translating Mod/File.hs, to $OUTPUT/Mod/File.v, also generate $METADATA/Mod/File.h2c, where $METADATA = $OUTPUT by default.

  2. Pass in search directories when converting a file. For example, if working with base, you'd specify -M path/to/base/output (flag name subject to change).

  3. When translating a file that does import M, hs-to-coq would go and load M.h2c. That would specify (a) what other h2c files to import; (b) metadata, e.g. constructor names; and (c) "persistent" edits, such as skip method or (I think) skip module. If it had already been loaded or generated, this would be brought in from memory, instead of from disk.

Re. 3, however, one question is: would these changes have to be specific to the module that imported them, or could they be globally loaded? Information about the constructors of Full.Mod.Type is always applicable because it's fully qualified. In that case, we could eagerly load all the .h2c files, or possibly even only generate one per library rather than one per module.

Precedence bug

For the following Haskell source:

eqString :: String -> String -> Bool
eqString []       []       = True
eqString (c1:cs1) (c2:cs2) = c1 == c2 && cs1 `eqString` cs2
eqString _        _        = False

The output I get for the RHS on the second line is

 (eqString (andb (c1 == c2) cs1) cs2)

instead of

 (andb (c1 == c2) (eqString cs1 cs2))

(To test, uncomment skip eqString in examples/ghc-base/Base/edits`)
Where should I look to debug this issue?

Bugs while translating guards and pattern matchings

I have created a minimal example that can reproduce this bug under examples/guard.

The Haskell file contains the following three functions:

f :: Int -> Int
f x | x == 1    = 1
    | otherwise = 2

g :: Int -> Int
g 1 = 1
g _ = 2

h :: Int -> Int
h x = if x == 1 then 1 else 2

hs-to-coq fails to translate f.

It can translate g but the translated Coq file cannot be compiled (because the translated code uses ==, which is a notation must be imported from GHC.Base).

It can successfully translate h.

multiline edits

Making each edit take exactly one line is harsh for redefine / add edits.

Can we add a multiline-block to the parser so that instead of

redefine Local Definition instance_GHC_Base_Eq__Boxity_op_zsze__ : Boxity -> (Boxity -> bool) := fun arg_319__ arg_320__ =>  match arg_319__ , arg_320__ with | a , b => negb (instance_GHC_Base_Eq__Boxity_op_zeze__ a b)  end.  

we can write

redefine {{ Local Definition instance_GHC_Base_Eq__Boxity_op_zsze__ : Boxity -> (Boxity -> bool) := 
    fun arg_319__ arg_320__ =>  
        match arg_319__ , arg_320__ with 
            | a , b => negb (instance_GHC_Base_Eq__Boxity_op_zeze__ a b)  
        end. 
}}

Split out the examples from the source code

There's a lot going on in this repository:

  1. The hs-to-coq conversion tool itself
  2. An abandoned GHC plugin that enables converting between structurally isomorphic types
  3. The converted parts of the base library
  4. Other converted examples

It would be nice to split this up into multiple repositories, because they're conceptually separate. The downside, of course, is that the examples depend on base which depends on hs-to-coq.

Unbound variable `a` in `Monoid (Endo a)` instance

This code (also in examples/test/Endo.v)

module Endo where

import Prelude hiding (Monoid)

class Monoid a where
        mempty  :: a
        mappend :: a -> a -> a
        mconcat :: [a] -> a

newtype Endo a = Endo { appEndo :: a -> a }

instance Monoid (Endo a) where
        mempty = Endo id
        Endo f `mappend` Endo g = Endo (f . g)
        mconcat = foldr Endo.mappend Endo.mempty

produces

Local Definition instance_Monoid__Endo_a__mempty : (Endo a) :=
  Mk_Endo id.

Note how a is not bound!

Automatically generating Unpeel instances for newtypes

Many base module edit files include this for newtype coercions

add Data.Monoid Instance Unpeel_Dual a : Unpeel (Dual a) a :=
	 Build_Unpeel _ _ getDual Mk_Dual.

We shouldn't have to add these via an edit, though. Should just generate them whenever we see a newtype definition.

Polymorpic type class with superclasses fails to translate

Possibly due to the fix of #9, the following code does not compile:

module PolyInstance3 where
class N a where  bar :: a
class N a => M a where foo :: a
instance N [a] where bar = []
instance M a => M [a] where foo = [foo]

The problem is that Coq makes the type argument of M implicit, which is not helpful in

Instance instance_forall___M_a___M__list_a_ : !forall {a}, forall `{M a}, M (list a) := {
  foo := instance_forall___M_a___M__list_a__foo }.

A better placed ! would help. Or maybe, instead of having to mess with bangs, make the first argument of M explicit:

Arguments M _ {_}.

Data.Functor.Const

If we try to translate Data.Functor.Const, some of the output includes an extra type variable inst_k that is unused. Coq can't figure out the kind of this variable and won't default it, so it gets rejected.

For example, here is part of the (newtype-derived) Ord instance:

Local Definition instance_forall___GHC_Base_Ord_a___GHC_Base_Ord__Const_a_b__compare {inst_a}
                                                                                     {inst_k} {inst_b} `{GHC.Base.Ord
                                                                                     inst_a} : Const inst_a
                                                                                               inst_b -> Const inst_a
                                                                                               inst_b -> comparison :=
  GHC.Prim.coerce GHC.Base.compare.

Pattern guards with fall-through semantics

I want a better overview of what is missing, so I’ll start creating tickets.

data Option a = Some a | None

somePred1 x = False
somePred2 x = False

foo x | Some True <- x  = 1
foo x | Some False <- x = 2
foo x | somePred1 x      = 3
foo x | somePred2 x      = 3

produces

Definition foo := (fun __arg_2__ =>
                    (match __arg_2__ with
                      | x => (match x with
                               | (Mk_Some True) => #1
                               | _ => _(*MissingValue*)
                             end)
                      | x => (match x with
                               | (Mk_Some False) => #2
                               | _ => _(*MissingValue*)
                             end)
                      | x => (if (somePred1 x)
                             then #3
                             else _(*MissingValue*))
                      | x => (if (somePred2 x)
                             then #3
                             else _(*MissingValue*))
                    end)).

but should fall through.

Cannot generate instance for -> in Control.Category

If we switch from HANDMOD to MODULES for Control.Category, the translation succeeds but we miss an instance

(* Translating `instance Category GHC.Prim.arrow' failed: OOPS! Cannot find
   information for class "Category" unsupported *)

The Category class is defined in the same file so the class information should be available.

Need a before/after edit

I want to be able to insert arbitrary Coq code right before or after a particular point in the file. Not just at the preamble.

after blah {{ Definition ...  }}

I don't think we need to parse the part between the {{ ... }}, just splice it into the file at the appropriate point.

Scoped type variables in instances

If type class instances use scoped type variables, they will fail.

There is an explicit comment in the function HsToCoq.ConvertHaskell.Declarations.Instances.topoSortInstance:

-- ASSUMPTION: type variables don't show up in terms. Broken
-- by ScopedTypeVariables.

Notation in a post-renamer work

This is not pressing, but I wanted to note down some thoughts before I lose them.

We currently Require imported modules (no Import), and every imported entity is addressed fully qualified (GHC.Base.map). This is nice, as we don’t have to worry about Haskell’s complex import/export structure or have problems with definitions that have clashing names.

This unfortunately does not allow us to use nice notation, in particular for binary operators. All these are now prefix operators (with z-encoded names…).

Here are two variants to work around this:

  • All definitions become Local Definition, all imports becomes Require Import. Because the definitions are Local, the Import does not import them, so we are in basically the situation as above. But we do get all notations.

    The disadvantage is that if we want the definitions to be in scope unqualified (e.g. for proving), then we cannot do that.

  • Slightly better: Every module defines all notations in a Module Notations. … End Notations. block. We import a module Foo with Require Foo. Import Foo.Notations.

    This should fix the problem with getting the names unqualified if we want to. A downside is the slightly more verbose importing (but I think it is fine.)

    If we want to use Foo’s notation inside Foo, we can simply declare every Notation twice: Once in the code, right after its definition, and then again all Notations at the end of the file, in the Notations module.

Orthogonal issue: Do we want an operator + in Foo to be (also) available as _Foo.+_, i.e. a infix-but-manually-qualified version?

DefaultSignatures

Semigroup.hs used the DefaultSignatures extension to define the Semigroup type class:

class Semigroup a where
  (<>) :: a -> a -> a

  default (<>) :: Monoid a => a -> a -> a
  (<>) = mappend

  sconcat :: NonEmpty a -> a
  sconcat = ... 
  
  stimes :: Integral b => b -> a -> a
  stimes = ...

Notice that the default method has a different type signature.

hs-to-coq will translate the above type class into the following (wrong) Coq code:

Record Semigroup__Dict a := Semigroup__Dict_Build {
  sappend__ : forall `{GHC.Base.Monoid a}, a -> a -> a ;
  sconcat__ : Data.List.NonEmpty.NonEmpty a -> a ;
  stimes__ : forall {b}, forall `{GHC.Real.Integral b}, b -> a -> a }.

The Monoid constraint should not appear in the type signature.

Skipping impossible guard condition/ Skipping certain macro expansions

Data.Set contains the following definition:

elem = go
  where STRICT_1_OF_2(go)
        go _ Tip = False
        go x (Bin _ y l r) = x == y || go x l || go x r

where STRICT_1_OF_2 is a macro defined as:

#define STRICT_1_OF_2(fn) fn arg _ | arg `seq` False = undefined

It is used to improve performance by avoiding unneeded laziness, but this does not matter in the translated Coq version, so I would like to skip this macro expansion, as expanding that macro raises the complexity of the function, and introduces undefined.

An alternative way to handle this problem is that if we have some heuristics to tell the condition here (arg `seq` False) always evaluates to False, we can ignore this branch during translation.

Uniques and UniqSupply need to have native coq implementations

I expect that we will have trouble proving anything useful about, say, CoreSubst if functions like uniqAway or other code that needs to get a fresh Unique are not total.

But GHC’s implementation of Unique is an Int, which is too small to always have a fresh one. Further more, UniqueSupply uses unsafePerformIO and C code to efficiently create new Uniques.

I have the gut feeling that we will have to implement the types Unique and UniqSupply in Coq, using actual nat (or maybe Char * Integer) as the representation, and implement UniqSupply purely, and have the code translation map operations involving Unique and UniqSupply use our implementation.

Constructors needs parameters of their data type declared maximally inserted.

This code

data Pair a = Pair a a

currently produces

Inductive Pair a : Type := Mk_Pair : a -> (a -> (Pair a)).

with

Inductive Pair (a : Type) : Type :=  Mk_Pair : a -> a -> Pair a

For Mk_Pair: Argument a is implicit
For Pair: Argument scope is [type_scope]
For Mk_Pair: Argument scopes are [type_scope _ _]

I believe it should produce

Inductive Pair a : Type := Mk_Pair : a -> (a -> (Pair a)).
Arguments Mk_Pair {a}.

so that

Inductive Pair (a : Type) : Type :=  Mk_Pair : a -> a -> Pair a

For Mk_Pair: Argument a is implicit and maximally inserted
For Pair: Argument scope is [type_scope]
For Mk_Pair: Argument scopes are [type_scope _ _]

Otherwise partial applications as in

Local Definition traferse_29__ : (forall {a} {b} {f},
      (forall `{Abblicative f}, (a -> (f b)) -> ((Pair a) -> (f (Pair b))))) :=
  fun {a} {b} {f} `{Abblicative f} =>
    fun arg_25__  arg_26__ =>
      match arg_25__ , arg_26__ with
        | f , (Mk_Pair x y) => ((purr Mk_Pair <**> f x) <**> f y)
      end.

do not work.

Shorter instance names

We currently create instance names that are absurdly wrong:

instance_forall___GHC_Base_Monoid_a____GHC_Base_Monoid_b____GHC_Base_Monoid_c____GHC_Base_Monoid_d____GHC_Base_Monoid_e___GHC_Base_Monoid__a___b___c___d___e_

Also, since we base the name on the pretty-printed instance head, instances of types with symbols (which are translated to _) have clashing names (this occurs for Generic instances).

At some point the hope was that users would not have deal with these names; in this case this would all be fine. But the names show up in proofs, so we should make them concise and to the point.

I plan to change them to simply

ClassName__InstTyCon

when the instance is for a specific type constructor or

ClassName__a

if it is of the form instance Class a.

This is good enough as long as everything in Haskell98 and one does not translate a module that has two instances where class and or instance type have the same base name, but different module names. But let's not let perfect be the enemy of usable.

Move conversion after the renamer

In order to deal with both overlapping names between modules and, surprisingly, operator precedence, we need to move the conversion process after the renamer, instead of simply after the parser. The biggest change will be that RdrName will become Name, and then that certain PlaceHolders might turn into actual data.

Makeshift solution for deriving Eq

Right now, everytime we do deriving Eq, we need to add

redefine Local Definition instance_GHC_Base_Eq__Boxity_op_zsze__ : Boxity -> (Boxity -> bool) := fun arg_319__ arg_320__ =>  match arg_319__ , arg_320__ with | a , b => negb (instance_GHC_Base_Eq__Boxity_op_zeze__ a b)  end.

to the edits file.

Fixing this in a principled way is challenging. But for now, we can workaround by dropping /= from the Eq type class and defining /= as a separate function.

Notation for "<" in GHC/Base.v

The midamble.v file for GHC.Base defines the notation

Infix "<" := (op_zl__) (no associativity, at level 70).

However, this notation conflicts with Coq's default notation for lt, the less-than proposition.
Furthermore, this notation is not defined in a notation scope or in a submodule, so any file that imports the Prelude imports it.

I prefer using the notation "<?" for this operation (in line with the rest of Coq's libraries) instead of Haskell's notation. This makes it more clear that it is a bool returning function, not a prop. Others may disagree --- please discuss.

But, regardless, we should edit Base to make this notation more controllable.

ExistentialQuantification not supported

This comes up while trying to formalize Streams not sure how relevant it is for GHC.

data Stream a = forall s. Stream (s -> Step s a) s

yields

Inductive Stream a : Type := Mk_Stream {s} : (s -> (Step s a)) -> (s -> (Stream a)).

which is invalid syntax; the {s} needs to be on the right of the colon.

Test case in examples/tests/Existential/

Sort defintions more carefully

We have to do a topological sort to mix instance declarations and value declarations, and also to get instance declarations in the right order. Currently, this uses topoSortSentences. I want to see if I can make this function, or another function, a bit better at preserving the original order, so that we have to emit less order edits when things are in the right order in the source code already. examples/successors is an example for that.

skipping all uses of a type

It would be convenient to be able to say

skip type Outputable.SDoc

and have it skip all functions that use that type.

This would replace individual skips of functions throughout the development, such as these from
module-edits/SrcLoc/edits.

pprUserRealSpan
pprUserSpan

I don't think it should skip type definitions that depend that type. I think we'll need ad hoc solutions for those cases. (Either skipping those types too, or redefining them so that they don't mention the skipped type.)

Add edit for Inductive type parameter kinds

We cannot currently translate

newtype ArrowMonad a b = ArrowMonad (a () b)

because the type of a is higher order. In this case I've been adding the correct definition to the preamble

Inductive ArrowMonad (a : Type -> Type -> Type) b : Type := Mk_ArrowMonad : ((a unit b) -> ArrowMonad a b).

along with an edit

rename value ArrowMonad = Mk_ArrowMonad

(Perhaps I could get a 'redefine' edit to work, but that hasn't worked out for me.)

It would be better if hs-to-coq knew about this datatype definition anyways. So something like

 param kind ArrowMonad (a : Type -> Type -> Type) (b : Type)

would provide just the information we need.

This also needs to apply to classes, such as

Class Category (cat : Type -> Type -> Type) := {
  id : forall {a}, cat a a ;
  op_z2218U__ : forall {b} {c} {a}, cat b c -> cat a b -> cat a c }.

No automatic munging of constructor names

Since not all constructors are punned, it might be easier, more reliable and following the principle of least surprise if we simply require the user to rename punned in an edit, and do no manual Mk_ munging at all. (Suggestion by @sweirich)

Can't rename type class members

Data.Semigroup defines includes (<>) as a class member which conflicts with Coq's notation for not equals. I'd like to rename it to something else, but 'rename' edits don't work for class members.

Data/type families unsupported

Currently, the presence of any data/type families in the input prevents the whole file from being translated.

For example, see base/Data/Either.hs

We should just skip them (or eventually, translate them).

deriving Ord for "Width" type in CmmType.hs

data Width   = W8 | W16 | W32 | W64
             | W80      -- Extended double-precision float,
                        -- used in x86 native codegen only.
                        -- (we use Ord, so it'd better be in this order)
             | W128
             | W256
             | W512
             deriving (Eq, Ord, Show)

The output of the derived Ord instance of this datatype looks weird. I'm not sure what is going on. Maybe something to do with Enum?

Simple pattern matches should stay simple

The current code (introduced in #1) uses complex chains of single-constructor pattern matches even when it is not needed, such as in the definition of map. At least in these simple cases, we should produce a single, complete pattern match also in Coq.

Tackle termination

The current plan to deal with non-obvious termination, in particular in local fix, is to disable Coq’s termination checker locally. This needs to be done.

Parameter of `Expr` should not be quantified in body

We currently have this for CoreExpr:

Inductive Expr : (forall b, Type) := Mk_Var : (forall {b}, (Id -> (Expr b)))
                                  |  Mk_Lit : (forall {b}, (Literal -> (Expr b)))
                                  |  Mk_App : (forall {b}, (((Expr b)) -> (((Expr b)) -> (Expr b))))
                                  |  Mk_Lam : (forall {b}, (b -> (((Expr b)) -> (Expr b))))
                                  |  Mk_Let : (forall {b}, (((Bind b)) -> (((Expr b)) -> (Expr b))))
                                  |  Mk_Case : (forall {b},
                                                 (((Expr b)) -> (b -> (Type_ -> ((list (Alt b)) -> (Expr b))))))
                                  |  Mk_Cast : (forall {b}, (((Expr b)) -> (Coercion -> (Expr b))))
                                  |  Mk_Tick : (forall {b}, (((Tickish Id)) -> (((Expr b)) -> (Expr b))))
                                  |  Mk_Type : (forall {b}, (Type_ -> (Expr b)))
                                  |  Mk_Coercion : (forall {b}, (Coercion -> (Expr b)))
with Bind : (forall b, Type) := Mk_NonRec : (forall {b},
                                              (b -> (((Expr b)) -> (Bind b))))
                             |  Mk_Rec : (forall {b}, ((list (b * ((Expr b)))) -> (Bind b)))
where "'Arg'" := ((Synonym Arg__raw (fun b => ((Expr b)%type))))
and   "'Alt'" := ((Synonym Alt__raw (fun b =>
                             (((AltCon * (list b)) * (Expr b))%type)))).

this is accepted by Coq, but it does not work well when defining a function over a CoreExpr: If you are in, say, the Mk_App case, you get a fresh type T for the binders of the subexpresions. It needs be the same type.

This seems to work better:

Inductive Expr b : Type := Mk_Var : ((Id -> (Expr b)))
                        |  Mk_Lit : ((Literal -> (Expr b)))
                        |  Mk_App : ((((Expr b)) -> (((Expr b)) -> (Expr b))))
                        |  Mk_Lam : ((b -> (((Expr b)) -> (Expr b))))
                        |  Mk_Let : ((((Bind b)) -> (((Expr b)) -> (Expr b))))
                        |  Mk_Case : ((((Expr b)) -> (b -> (Type_ -> ((list (((AltCon * (list b)) * (Expr b))%type)) -> (Expr b))))))
                        |  Mk_Cast : ((((Expr b)) -> (Coercion -> (Expr b))))
                        |  Mk_Tick : ((((Tickish Id)) -> (((Expr b)) -> (Expr b))))
                        |  Mk_Type : ((Type_ -> (Expr b)))
                        |  Mk_Coercion : ((Coercion -> (Expr b)))
with Bind b : Type := Mk_NonRec : ((b -> (((Expr b)) -> (Bind b))))
                   |  Mk_Rec : (((list (b * ((Expr b)))) -> (Bind b))).

Notation "'Arg'" := ((Synonym Arg__raw (fun b => ((Expr b)%type)))).
Notation "'Alt'" := ((Synonym Alt__raw (fun b =>(((AltCon * (list b)) * (Expr b))%type)))).

(Not sure if there is a way of using the type synonyms in the Inductive.)

Should we use a "default value" type class for Panic.panic?

Many uses of Panic.panic in CmmTypes.hs are with concrete result types (integer, width, etc).

If we have a class for default values, then we can safely parameterize the panic function with this class.

Parameter panic {a} `{Default a} : String -> a

Operators as function parameters

(This is not urgent, marking for future reference).

Data.Function has this annoying definition that we can't currently handle.

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*.) `on` f = \x y -> f x .*. f y

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.