Finite sets
Jan. 6th, 2013 08:05 pmSo, I just encountered a most delicious type the other day:
class Finite a where
assemble :: Applicative f => (a -> f b) -> f (a -> b)
What's so nice about it is that the only way you can implement it is if the type a is in fact finite. (But see the notes.) So the questions are:
- Can you see why?
- Can you figure out how to implement it for some chosen finite type?
- Can you figure out how to implement it in general, given a list of all the values? (you may assume
Eq afor this one) - Can you figure out how to get a list of all the values, given some arbitrary implementation of
assemble?
Well, of course you can implement anything in Haskell by using undefined or equivalent. For the sake of these problems, assume you're constrained to use only fully-defined functions.
And really, there's nothing here that truly forces the type to be finite. In order to get some real logical guarantees, you should assume you're in a total language (preferably a provably-total language), and you should use the following dependent type instead:
class Finite a where
assemble :: Applicative f => ((x::a) -> f (b x)) -> f ((x::a) -> b x)
Missing some laws
Date: 2013-01-14 06:26 pm (UTC)As long as we have one element of the type we can implement the rest, finite or not. Perhaps there were other constraints that an implementation should satisfy.
Re: Missing some laws
Date: 2013-01-15 01:11 am (UTC)Of course, as an attempt to enumerate all values in the type, your instance isn't morally correct. In this case, the morality in question can be enforced with dependent types. Can you find any way to break the dependent version? (nontermination doesn't count.)
no subject
Date: 2013-01-16 09:40 pm (UTC)My solution for assemble when given [a]:
assemble values f = select <$> traverse (\x -> fmap (\y -> (x,y)) (f x)) values
where select l x = fromJust (lookup x l)
I haven't figured out how to get [a] when given assemble.
no subject
Date: 2013-01-16 10:07 pm (UTC)Having experimented with my assemble' definition, I don't think it is possible to get Finite a => [a] given just the definition of assemble. In particular, I have not found a way to make the following hold:
exists f. forall values. valuesOf (assemble' values) == values
That is, a definition function valuesOf that takes the definition of assemble and produces a list of all values can't retrieve the values given to assemble'. As far as I can tell, with my assemble' definition, differentiating between assemble' [1,2,3] and assemble' [1,2,4] doesn't seem possible.
The amount of values of that type can be recovered, though. Pass \x -> [x,x] as argument to assemble. The length of the resulting list will be 2^amount. If you pass \x -> [x,x,x], the resulting list will have 3^amount elements.
no subject
Date: 2013-01-18 02:55 am (UTC)domain :: Finite a => [a]domain = toList . execWriter . assemble $ tell . return
Where
toListis from DList and brings the runtime down to O(n) instead of O(n^2) due to the writer monad always appending to the right.no subject
Date: 2013-01-18 04:23 am (UTC)