Nástroj sql-tap je proxy mezi aplikací a databází, které zachytává všechny SQL dotazy a zobrazuje je v terminálovém rozhraní. Zde lze téměř v reálném čase zkoumat dotazy, sledovat transakce a spouštět SQL příkaz EXPLAIN. Podporované databázové systémy jsou pouze PostgreSQL a MySQL. Zdrojový kód je dostupný na GitHubu, pod licencí MIT.
Byla vydána nová verze 9.2 textového editoru Vim (Vi IMproved). Přináší vylepšené doplňování, podporu schránky ve Waylandu, podporu XDG Base Directory (konfigurace v $HOME/.config/vim), vylepšené Vim9 skriptování nebo lepší zvýrazňování změn. Vim zůstává charityware. Nadále vybízí k podpoře dětí v Ugandě. Z důvodu úmrtí autora Vimu Brama Moolenaara a ukončení činnosti jím založené charitativní organizace ICCF Holland projekt Vim navázal spolupráci s charitativní organizaci Kuwasha.
Byl představen editor MonoSketch, webová aplikace pro tvorbu diagramů, technických nákresů, flowchartů a různých dalších vizualizací, to vše jenom z ASCII znaků. Všechny operace běží pouze v prohlížeči uživatele a neprobíhá tedy žádné nahrávání dat na server. Zdrojový kód aplikace (drtivá většina Kotlin, žádné C#) je dostupný na GitHubu pod licencí Apache 2.0.
Byla vydána nová verze 3.7.0 multiplatformního svobodného frameworku pro zpracování obrazu G'MIC (GREYC's Magic for Image Computing, Wikipedie). Přehled novinek i s náhledy nových filtrů na PIXLS.US.
Všem na AbcLinuxu vše nejlepší k Valentýnu aneb Dni lásky ke svobodnému softwaru (I love Free Software Day, Mastodon, 𝕏).
Eric Migicovsky představil Pebble Emulator, tj. emulátor hodinek Pebble (PebbleOS) běžící ve webovém prohlížeči. Za 6 hodin jej napsal Claude Code. Zdrojové kódy jsou k dispozici na GitHubu.
Byla vydána nová verze 3.41 frameworku Flutter (Wikipedie) pro vývoj mobilních, webových i desktopových aplikací a nová verze 3.11 souvisejícího programovacího jazyka Dart (Wikipedie).
Rusko zcela zablokovalo komunikační platformu WhatsApp, řekl včera mluvčí Kremlu Dmitrij Peskov. Aplikace, jejímž vlastníkem je americká společnost Meta Platforms a která má v Rusku na 100 milionů uživatelů, podle Peskova nedodržovala ruské zákony. Mluvčí zároveň lidem v Rusku doporučil, aby začali používat domácí aplikaci MAX. Kritici tvrdí, že tato aplikace ruské vládě umožňuje lidi sledovat, což úřady popírají.
Před 34 lety, ve čtvrtek 13. února 1992, se tehdejší Česká a Slovenská Federativní Republika oficiálně (a slavnostně) připojila k Internetu.
Agent umělé inteligence vytvořil 'útočný' článek o Scottu Shambaughovi, dobrovolném správci knihovny matplotlib, poté, co vývojář odmítl agentem navrženou změnu kódu (pull request). 'Uražený' agent autonomně sepsal a publikoval na svém blogu článek, který přisuzuje Shambaughovi smyšlené motivace, egoismus a strach z AI coby konkurence.
For me the greatest beauty always lies in the greatest clarity.
V tomto zápisku si ukážeme jednu užitečnou schopnost Emacs módu pro jazyk Agda. Jedná se o automatické napsání kódu, kdy programátor pouze specifikuje, co má kód dělat, a nechá editor, aby takový kód napsal.
Naším cílem bude napsat funkci zap. zap dostane seznam funkcí a stejně dlouhý seznam prvků a na každý prvek aplikuje
odpovídající funkci. Například výsledkem zap (suc ∷ suc ∷ id ∷ (suc ∘ suc) ∷ []) (1 ∷ 2 ∷ 3 ∷ 4 ∷ []) bude seznam 2 ∷ 3 ∷ 3 ∷ 6 ∷ []. Pro pořádek doplňme, že suc x je číslo o jedna větší než x (od slova successor), id je identita, ∘ značí skládání funkcí, ∷ značí cons (dostane prvek a seznam a zkonstruuje nový seznam, který začíná daným prvkem a pokračuje daným seznamem) a [] značí prázdný seznam (například 0 ∷ [] je seznam obsahující číslo 0).
Jazyk Agda je minimalistický – čísla ani seznamy nejsou jeho součástí, tudíž aby fungoval příklad uvedený výše,
budeme muset napsat funkce id, ∘ a zap a definovat datový typ pro přirozená čísla ℕ a datové typy pro seznamy Vec.
Začneme identitou – funkcí, která vrátí to, co dostane. Napíšeme typ, levou stranu funkce a místo pravé strany dáme otazník (kód, který patří místo otazníku, bude doplněn automaticky):
id : {A : Set} → A → A
id x = ?
Funkce má dva parametry – množinu a její prvek. Složené závorky kolem prvního parametru
značí, že se jedná o implicitní parametr – kompilátor se pokusí doplnit argument automaticky.
Nyní Emacs požádáme, aby doplnil kód. Nejprve použijeme příkaz Load (C-c C-l), ten provede
zvýraznění kódu a otazník změní na chlívek { }0 vymezený složenými závorkami (mezi složené závorky jde psát).
Chlívek můžeme chápat jako díru ve zdrojovém kódu, kterou je třeba vyplnit.
Chlívky jsou očíslovány (náš má číslo 0) a lze se mezi nimi pohybovat pomocí příkazů Next Goal (C-c C-f) a Previous Goal (C-c C-b).
Když je kurzor v chlívku, lze použít příkaz Auto (C-c C-a) a Emacs se pokusí napsat kód automaticky.
V tomto případě Emacs automaticky napíše x:
id : {A : Set} → A → A
id x = x
Tento příklad pravděpodobně člověka na zadek neposadí, zkusme skládání funkcí. Postup je stejný. Napíšeme typ, levou stranu funkce a místo pravé strany dáme otazník:
_∘_ : {A B C : Set} → (B → C) → (A → B) → (A → C)
g ∘ f = ?
Podtržítka v názvu funkce _∘_ značí místa, kam přijdou argumenty (například if—then—else lze definovat jako funkci if_then_else_ se třemi parametry).
∘ pro skládání funkcí má tři implicitní parametry. Nyní požádáme Emacs o doplnění kódu (příkaz Load, přesun do vzniklého chlívku, příkaz Auto) a dostaneme:
_∘_ : {A B C : Set} → (B → C) → (A → B) → (A → C)
g ∘ f = λ z → g (f z)
Emacs doplnil λ z → g (f z). Tohle už je zajímavajší, ne?
Vec budou seznamy opatřené délkou (součástí typu bude i délka seznamu). Délku budeme reprezentovat přirozeným číslem.
Napřed tedy nadefinujeme množinu přirozených čísel:
data ℕ : Set where zero : ℕ suc : ℕ → ℕ
Význam definice:
ℕ je nejmenší množina pro níž platí“.ℕ obsahuje zero“ (rozuměj: nula je přirozené číslo).ℕ prvek n, pak také obsahuje prvek suc n“
(rozuměj: je-li n přirozené číslo, pak i n + 1 je přirozené číslo).Přirozená čísla 0, 1, 2, 3 pak zapisujeme zero, suc zero, suc (suc zero), suc (suc (suc zero))
Abychom mohli používat známý zápis v desítkové soustavě, řekneme Agdě následující:
{-# BUILTIN NATURAL ℕ #-}
{-# BUILTIN ZERO zero #-}
{-# BUILTIN SUC suc #-}
Zápisem 2 pak Agda bude rozumět suc (suc zero).
Nyní můžeme zadefinovat seznamy s délkou (seznamy bez délky se často označují jako List a ty s délkou jako Vec nebo Vector).
Na rozdíl od přirozených čísel nedefinujeme jednu množinu, ale celou rodinu množin.
Pro každou množinu A a přirozené číslo n definujeme množinu seznamů
délky n s prvky z množiny A:
data Vec (A : Set) : ℕ → Set where
[] : Vec A zero
_∷_ : {n : ℕ} → A → Vec A n → Vec A (suc n)
Význam definice:
A a přirozené číslo n je Vec A n nejmenší množina pro níž platí“.[] je v množině Vec A zero“ (rozuměj: prázdný seznam patří do množiny seznamů délky nula).x prvek z množiny A a xs je seznam délky n nad množinou A, tak x ∷ xs je seznam délky n + 1 nad množinou A“.Aby se ∷ parsoval jako doprava asociativní, je třeba přidat následující řádek:
infixr 5 _∷_
Konečně můžeme definovat funkci zap. Budeme postupovat stejně jako v předchozích případech.
Napíšeme typ funkce, levou stranu a místo pravé strany dáme otazník:
zap : {A B : Set} {n : ℕ} → Vec (A → B) n → Vec A n → Vec B n
zap fs xs = ?
Příkazem Load vytvoříme chlívek. Když bychom nyní zajeli kurzorem do chlívku a použili příkaz
Auto, doplnění kódu se nepodaří. Funkci je třeba definovat rozborem případů a to standardně
Auto nedělá. Do chlívku je třeba napsat -c, což povolí rozbor případů (case split)
a nyní můžeme použít příkaz Auto a Emacs napíše
zap : {A B : Set} {n : ℕ} → Vec (A → B) n → Vec A n → Vec B n
zap [] xs = []
zap (x ∷ x₁) (x₂ ∷ x₃) = x x₂ ∷ zap x₁ x₃
Kód je v pořádku až na pojmenování proměnných, to už musíme opravit ručně:
zap : {A B : Set} {n : ℕ} → Vec (A → B) n → Vec A n → Vec B n
zap [] _ = []
zap (f ∷ fs) (x ∷ xs) = f x ∷ zap fs xs
Všimněte si, že v definici funkce chybí případ, kdy je
seznam funkcí prázdný a seznam prvků neprázdný.
Důvodem je, že typ funkce zap říká, že všechny seznamy mají délku n (jsou tedy stejně dlouhé).
Drobná potíž je, že ne vždy příkaz Auto najde program, který požadujeme.
Ukážeme si to na příkladu s funkcí not, která by měla negovat
booleovskou hodnotu. Protože Agda neobsahuje typ Bool, musíme ho napřed zadefinovat:
data Bool : Set where true : Bool false : Bool
Nyní můžeme chtít napsat funkci not:
not : Bool → Bool not x = ?
Po využití příkazu Auto dostaneme:
not : Bool → Bool not x = xTo je ale špatně, chtěli jsme:
not : Bool → Bool not true = false not false = trueDalší informace o příkazu Auto je možné najít na stránkách Agdy. Na závěr můžeme pomocí příkazu Evaluate term to normal form (C-c C-n) vyzkoušet, zda
zap funguje. A opravdu, po stisku kláves C-c C-n a zadání zap (suc ∷ suc ∷ id ∷ (suc ∘ suc) ∷ []) (1 ∷ 2 ∷ 3 ∷ 4 ∷ []) dostaneme výsledek 2 ∷ 3 ∷ 3 ∷ 6 ∷ [].
Tiskni
Sdílej:
Bez lidske inteligence si nemuze poradit ani s takovou trivialitou jako je treba odvozeni funkce (operatoru) nerovnosti:
-- nejprve operator ekvivalence
(==) :: Eq a => a -> a -> Bool
-- nerovnost ?
(/=) ? Eq a => a -> a -> Bool
-- error: cannot infer
-- musi natukat clovek
x /= y == not (x == y)
-- a je to :)
x /= y = not (x == y)
Bez lidske inteligence si nemuze poradit ani s takovou trivialitou jako je treba odvozeni funkce (operatoru) nerovnosti:
Docela mě překvapuje, že to nevrátí třeba x /= y = True.
Příkaz Auto zvládne doplnit i složitější výrazy. Například return a bind pro stavovou monádu doplní takto:
record Pair (A B : Set) : Set where
constructor _,_
field
proj₁ : A
proj₂ : B
record State (S A : Set) : Set where
constructor state
field
runState : S → Pair S A
-- vygenerovane prikazem Auto
return : {S A : Set} → A → State S A
return x = state (λ z → z , x)
-- vygenerovane prikazem Auto (a spatne)
bind : {S A B : Set} → State S A → (A → State S B) → State S B
bind m f = state
(λ z →
z ,
Pair.proj₂
(State.runState (f (Pair.proj₂ (State.runState m z))) z))
bind je bohužel špatně – typ totiž nezakazuje použití původního stavu. Když ale umožním, aby se typ stavu měnil (pak už to není monáda), tak Auto vygeneruje již korektní definici i pro bind:
record IState (S₁ S₂ A : Set) : Set where
constructor state
field
runState : S₁ → Pair S₂ A
-- vygenerovane prikazem Auto
ibind : {S₁ S₂ S₃ A B : Set} → IState S₁ S₂ A → (A → IState S₂ S₃ B) → IState S₁ S₃ B
ibind m f = state
(λ z →
Pair.proj₁
(IState.runState (f (Pair.proj₂ (IState.runState m z)))
(Pair.proj₁ (IState.runState m z)))
,
Pair.proj₂
(IState.runState (f (Pair.proj₂ (IState.runState m z)))
(Pair.proj₁ (IState.runState m z))))
Nicméně perfektní to není – některé výrazy se tam zbytečně opakují, člověk by napsal:
-- napsane clovekem
ibind' : {S₁ S₂ S₃ A B : Set} → IState S₁ S₂ A → (A → IState S₂ S₃ B) → IState S₁ S₃ B
ibind' m f = state
(λ st₁ →
let (st₂ , a) = IState.runState m st₁
in IState.runState (f a) st₂)
IMHO to ale moc prakticky neni.Hodí se to v důkazech. Tam potřebuji najít term s daným typem a už příliš nezáleží na tom, jak ten term vypadá.
Bez Vimu si jiz nedokazi predstavit svuj zivot 
Ale ten Emacs ma spousty zajimavych funkci a doplnku, ktere bych rad pouzival a ve svete vimu jsou nedokonale imitovane. Napr. org mod a velmi kvalitni integrace REPLu funkcionalnich jazyku. No uvidim, treba se nekdy hacknu.
Hm, moc tomu nerozumim
Máte nějaký konkrétní dotaz, třeba bych mohl pomoci?
Mně se na Agdě a podobných jazycích líbí minimalističnost kombinovaná se silou typového systému. Naopak mi vadí absence aktuální definice jazyka – bylo by super, kdyby někdo zpracoval definici na úrovni Standard ML (viz stará verze: The Definition of Standard ML - Version 2).
Hlavní využití příkazu Auto je při hledání důkazů – tam totiž jde pouze o nalezení termu s odpovídajícím typem a je jedno, jak ten term vypadá. Je tohle odpověď na vaši otázku?
int f(int a, int b)a editor me k tomu doplnil:
{
return a + b;
}
i kdyz jsem mohl chtit odcitani, nasobeni, nebo neco slozitejsiho?
i kdyz jsem mohl chtit odcitani, nasobeni, nebo neco slozitejsiho?
Přesně tak. Například, když chci odčítání a použiji typ
binop₁ : ℕ → ℕ → ℕ
tak dostanu
binop₁ a b = b
což není odčítání. Musím tedy upřesnit typ:
binop₂ : (x : ℕ) → (y : ℕ) → Pair ℕ (minus_pred x y)
Místo pouhého čísla vracím dvojici. První prvek dvojice je číslo a druhý prvek je důkaz, že první prvek je rozdíl x a y. Odečítání definuji následovně:
_∸_ : ℕ → ℕ → ℕ m ∸ zero = m zero ∸ _ = zero suc m ∸ suc n = m ∸ n
Rovnost vyjadřuji pomocí následujícího typu. Typ je navržen tak, že term refl typu a ≡ b jde zkonstruovat pouze tehdy, jsou-li a a b stejné:
data _≡_ {A : Set} (x : A) : A → Set where
refl : x ≡ x
Následuje definice závislého páru, kde typ druhé složky závisí na hodnotě první složky:
record Pair (A : Set) (B : A → Set) : Set where
constructor _,_
field
proj₁ : A
proj₂ : B proj₁
Nastavení parseru:
infixl 6 _∸_ infix 4 _≡_ _,_
Funkce vracející typ (tj. výrok), že rozdíl prvních dvou čísel je roven třetímu číslu:
minus_pred : ℕ → ℕ → ℕ → Set minus_pred x y res = x ∸ y ≡ res
Pro tento typ už příkaz Auto vygeneruje požadovanou funkci:
binop₂ : (x : ℕ) → (y : ℕ) → Pair ℕ (minus_pred x y) binop₂ a b = a ∸ b , refl
Myslím, že neuniká. V ničem to není lepší. Je to jen příklad, že vlastnost výsledku funkce jde specifikovat typem. V tomto případě to však nemá žádné výhody – spíše naopak.
Příklad praktického použití je třeba funkce, která transformuje program a kde chceme, aby výsledný program dával stejné výsledky jako původní program.
Příklad praktického použití je třeba funkce, která transformuje program a kde chceme, aby výsledný program dával stejné výsledky jako původní program.Tohle větou jsi měl celý článek uvést
Vygenerovalo by to neco i kdybych nenadefinoval operator _-_ a minus_pred definoval jinym zpusobem - treba pomoci scitani?
Nejspíš ne.
Konkrétně, pokud máte na mysli podobnou definici
minus_pred : ℕ → ℕ → ℕ → Set minus_pred x y res = y + res ≡ x
tak ne. Problém je v tom, že pro x < y neexistuje přirozené číslo res a Auto hledá totální funkci (všude definovanou).
Kdybych zadefinoval relaci ≥ a funkci binop₂ definoval pouze pro x ≥ y, tak by to stejně nenašel – je to už příliš složité. Nezkoušel jsem to, ale myslím, že by se muselo nadefinovat ∸, pak dokázat lemma, že z x ≥ y a x ∸ y ≡ res plyne y + res ≡ x, a pak by to našel (ale to už není příliš zajímavé, protože je to vlastně celé hotové).