Skip to main content

Posts

Abstracting over Type Constructors using Dynamics in C#

I've written quite a few times about my experiments with the CLR type system [ 1 , 2 , 3 ]. After much exploration and reflection, I had devised a pretty good approach to encoding ML-style modules and abstracting over type constructors in C#. A recent question on Stack Overflow made me realize that I never actually explained this technique in plain English. The best encoding of ML modules and type constructor polymorphism requires the use of partly safe casting. An ML signature maps to a C# interface with a generic type parameter called a "brand". The brand names the class that implements the interface, ie. the module implementation. An ML module maps to a C# class. If the module implements a signature, then it implements the corresponding interface and specifies itself as the signature's brand. Since classes and interfaces are first-class values, an ML functor also maps to a class. An ML type component maps to an abstract class that shares the same brand as the modu...

Sasa v0.9.2 Released

The newest Sasa release contains a number of bugfixes and increased compliance with MIME standards, including proper MIME MailMessage subject decoding. Perhaps of wider interest to the .NET community, there are a number of extension methods for thread safe and null-safe event raising ; safe event raising is a major bane of the .NET developer's existence. There are specific overloads for all System.Action delegate types. A general RaiseAny extension method is also provided that isn't very efficient, but which should match the signature of any event in the class libraries. More overloads can be provided for more efficient execution if needed. Here is the complete list of changes from the changelog: = v0.9.2 = * fixed bug where quoted printable encoding failed when = was the last character. * added Pop3Session.Reset method. * compact serializer no longer uses stream positions to track cached objects, so non-indexable streams, like DeflateStream, are now usable. * ISerializi...

SlimTimer Timesheet Processing Utility

I use the very respectable SlimTimer to help me track my hours. Unfortunately, while they display a consistent total across all reports, the entries in each report do not necessarily add up to that total due to the fractional time units and the rounding involved. Unfortunately, the accounting department tends to frown upon inconsistencies like this, no matter the reason. My process thus far has been to simply export a full timesheet with the report settings specifying time units as precisely as possible, and then performing the sum myself on the resulting chart. This got a bit tedious, so I wrote a program to compile the necessary tallies over however many timesheet files I wanted to process. The source and binaries are available for download . Simply drag and drop any number of timesheets generated from SlimTimer, and the utility will generate a new csv file for each timesheet, with an extension "-out.csv". The format of the output csv file is formatted for my invoice struc...

Mobile Code in C# via Finally Tagless Interpreters

Awhile back I described an idea to transparently execute code server-side or client-side given the same program. I've finally gotten around to implementing this using my encoding for type constructor polymorphism in C#. Here is an example you can run from the original paper showcasing exponentiation which can execute transparently either server-side or client-side. The server-side code is intentionally limited to bases less than 100 and exponents less than 20. Here is some simplified code that defines an exponentiation function: void Build<B, R>(B _) where B : ISymantics<B>, new() { var e = _.Lambda<int, Func<int, int>>( x => _.Fix<int, int>(self => _.Lambda<int, int>(n => _.If(_.Lte(n, _.Int(0)), () => _.Int(1), () => _.Mul(x, _.Apply(self, _.Add(n, _.Int(-1)))))))); } The parameter "_" is the tagless interpeter and it's type is ISymant...

Sasa v0.9 Released

Sasa v0.9 has been released. See the changelog for a detailed description of the changes. Here is the original release description for Sasa v0.8. This post will describe only changes from v0.8. Backwards-incompatible changes: Renamed Sasa.Collections.List to Sasa.Collections.Seq to avoid clashes with System.Collections.Generic.List Restructured the list operators to better support chaining Useful additions include: Sasa.Weak<T> which wraps WeakReference Additional string processing functions, like StringExt.SliceEquals Array-processing combinators under Sasa.Collections.Arrays (Slice, Dup, etc.) Stream functions under Sasa.IO (CopyTo, ToArray) Support for MIME decoding and encoding for MailMessage parsing Bugfixes: Better conformance to RFCs for Pop3Client and MailMessage parsing Concurrency bugfix in Sasa.Lazy. MIME MailMessage parsing and the Pop3Client are already in use in production code, and conformance appears adequate after hundreds of processed messages. Experimental ...

Garbage Collection Representations Continued II

The tagged pointer representation described in Xavier Leroy's ZINC paper is compelling in its simplicity. Most data manipulated in typical programs is integer or pointer-based in some way, so using a 1-bit tagged representation allows unboxed integers, resulting in an efficient representation of the most common data types. I've never been satisfied with the size header in heap-allocated types though, and the two bits reserved for GC pretty much forces you to use some mark-sweep variant. Integrating something like age-oriented collection with reference counting for the old generation would require an entirely new word for every block of memory. This is a prohibitive cost in functional programs. Removing the Size Header Reading about BIBOP techniques used in the Streamflow allocator gave me the idea of using page masking to determine the block size. As in Streamflow, consider an allocator where each page obtained from the OS was partitioned into a list of equally-sized blocks. ...