[Agda] stdlib for practical programming
Dmytro Starosud
d.starosud at gmail.com
Fri Sep 27 20:34:47 CEST 2013
Ok, thank you.
I've understood, will implement my own Prelude.
P.S. Just want to note, that I wasn't saying Agda cannot something or
isn't powerful enough, the same for Standard Library. I just asked if
someone had already written "Prelude" library for practical
programming. For me it would be more convenient to use uniform way
instead of reinvented one. But now I see everyone does it :-)
Best regards,
Dmytro
2013/9/27 Sergei Meshveliani <mechvel at botik.ru>:
> On Thu, 2013-09-26 at 22:44 +0300, Dmytro Starosud wrote:
>> OK, I see I should have been more precise.
>> Yes, Standard library is "some library" but it doesn't allow enough
>> level of overloading.
>> What I need? A lot of stuff.
>> In particular I need map (fmap, _<$>_ whatever) function which will
>> work for any functor (Maybe, List, Vector, Product, mapable; IMapable
>> whatever).
>
> In Haskell this is achieved by the
> language feature of constructor classes.
>
> For example, Functor is a constructor class defined in the Haskell's
> library:
>
> class Functor c where fmap :: (a → b) → c a → c b
> -- fmap f (c a) --> c (f a)
>
> -- if I recall correctly!
> Here c ranges over unary type constructors.
> For example, c may be List, Maybe, ...
>
> I think that Agda does not need any additional language feature for
> this. This notion of Functor
> (let us call it FMap, because I am not sure that Haskell's `Functor'
> means something close to Functor of the category theory)
>
> is easily expressed via dependent types and records:
>
> record FMap (Cons : Set → Set) : Set (suc 0ℓ)
> where
> field fmap : {A B : Set} → (f : A → B) → Cons A → Cons B
>
> (I skip the Level arguments, so far).
> Here Cons correponds to `c' in Functor of the Haskell library.
>
> This c FMap an be set into Standard library.
>
> But I suspect that Standard library already has something for this,
> may be something better.
>
> Who knows, please, has it?
>
> Anyway here is an example of using overloading for fmap via the above
> FMap `class':
>
> ---------------------------------------------------------------------
> module FMap where
> open import Level using (suc) renaming (zero to 0ℓ)
> open import Data.Bool using (Bool; true; false)
> open import Data.Nat using (ℕ)
> open import Data.Product using (_×_; _,_)
> open import Data.List using (List; []; _∷_)
> open import Data.Maybe using (Maybe; just; nothing)
>
> -- First, define various instances for FMap.
> -- Such instances can be easily defined and set into the library:
>
> listFMap : FMap List -- here Cons == List
> listFMap = record{ fmap = fmap-l }
> where
> fmap-l : {A B : Set} → (f : A → B) → List A → List B
> fmap-l _ [] = []
> fmap-l f (x ∷ xs) = (f x) ∷ (fmap-l f xs)
>
> maybeFMap : FMap Maybe -- here Cons == Maybe
> maybeFMap = record{ fmap = fmap-mb }
> where
> fmap-mb : {A B : Set} → (f : A → B) → Maybe A → Maybe B
> fmap-mb f nothing = nothing
> fmap-mb f (just a) = just (f a)
> ---------------------------------------------------------------------------
>
> Example of usage:
>
> g : Maybe Bool → Maybe ℕ → Maybe ℕ × Maybe Bool
> g mbBoo mbN = (fmap f mbBoo , fmap h mbN)
> where
> open FMap maybeFMap
>
> f : Bool → ℕ
> f true = 1
> f false = 0
>
> h : ℕ → Bool
> h 1 = true
> h _ = false
>
> We see that fmap is used as overloaded.
>
>
>> I don't want import renaming ten modules just to do some simple things.
>> I was asking for library, which simplifies all this work.
>> e.g. I would like following:
>>
>> open import Prelude -- Prelude is this wanted "some library"
>> {- many useful stuff here -}
>>
>> instead of:
>>
>> open import Level renaming (zero to zeroL; suc to sucL; \lub to \lubL)
>> open import Data.Nat renaming (zero to zeroN; suc to sucN; \lub to \lubN; ...)
>> open import Data.List renaming (map to mapL; foldr to foldrL; ...)
>> open import Data.Vector renaming (map to mapV; foldr to foldrV; ...)
>> open import Data.Product renaming (map to mapP; ...)
>> etc. ...
>> etc. ...
>> etc. ...
>>
>> {- many useful stuff here -}
>>
>
> This `sugar' can (probably) be done by
>
> importing `classes' (done as records) and instances
> instead of separate functions.
>
> If Haskell and its library is considered as all right in this import
> matters, what is wrong with the Agda library in this point?
>
> For example, instead of zero and suc, one can import
> DistributiveLattice and its several instances
> (NatProp.distributiveLattice, Foo.distributiveLattice, ...)
>
> (a contrived example)
> and then to use overloading by open DistributiveLattice {{...}}
> and such.
> This will give importing items by _groups_.
>
> For example, 0#, 1# _+_; _*_ do not need to be renamed, because one
> can import the `classs' RingWithOne and several its instances.
>
> Introducing more `classes' and instances will support this style
> further.
>
> If I needed a single module Prelude
>
> which exports "everything I may needed", I could try to write
>
> module MyPrelude where
> open import Foo1 using (...) renaming (...)
> open import Foo2 using (...) renaming (...)
> ...
> somewhat use "open ... public",
>
> -- and do most of the import by `classes' and instances.
>
> I hope,
> this will join and re-export the needed things.
>
> I used this approach in Haskell to create a union DPrelude of
> MyProperPrelude and a large part of Standard library.
>
> How people think, will a similar approach work in Agda?
>
> (And as to my personal taste, I (currently) prefer to specify explicitly
> what is imported from each small module, because this way it is easier
> to control, to debug, to maintain
> ).
>
> Regards,
>
> ------
> Sergei
>
>
>
>
>
>
More information about the Agda
mailing list