← All posts tagged code

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\username\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.

import System.Process
import System.IO.Temp      -- dependencies: * temporary
import GHC.Vacuum.GraphViz --               * vacuum-graphviz

:{
let __spawn_graph xs = void $ do {
    view_png <- return $ system . ("feh " ++);
    withSystemTempFile "vacuum" $ \ path _ ->
        vacuumToPng path xs >>= view_png;
    }
:}

:def graph \xs -> return $ "__spawn_graph (" ++ xs ++ ")"

-- :graph Data.Set.fromList [1..20]

$ pip install --help
^CTraceback (most recent call last):
  File "/usr/bin/pip", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2727, in <module>
    add_activation_listener(lambda dist: dist.activate())
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 700, in subscribe
    callback(dist)
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2727, in <lambda>
    add_activation_listener(lambda dist: dist.activate())
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2227, in activate
    self.insert_on(path)
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2322, in insert_on
    version = self.version
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2179, in version
    for line in self._get_metadata('PKG-INFO'):
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2221, in _get_metadata
    for line in self.get_metadata_lines(name):
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1536, in get_metadata_lines
    return yield_lines(self.get_metadata(name))
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1530, in get_metadata
    metadata = f.read()
KeyboardInterrupt

Вот ещё табличка:
+-----+-----+-----+-----+-----+------+
|  *  |head |tail |cons |snoc |append|
+-----+-----+-----+-----+-----+------+
| []  |O(1) |O(1) |O(1) |O(n) | O(n) |
+-----+-----+-----+-----+-----+------+
|  X  |O(1) |O(1) |O(1) |O(1) | O(n) |
+-----+-----+-----+-----+-----+------+
|  Y  |O(1) |O(1) |O(1) |O(n) | O(1) |
+-----+-----+-----+-----+-----+------+
|DList|O(n) |O(n) |O(1) |O(1) | O(1) |
+-----+-----+-----+-----+-----+------+
где X, Y, DList есть:
data X a = (forall b. (a -> b -> b) -> b -> b) :<: X a | E
newtype Y a = Y (forall b. (a -> Y a -> b -> b) -> b -> b)
newtype DList a = DL ([a] -> [a])

Some people like to acknowledge both the operating system and
     kernel when they talk about their computers, so they might say
     they use "GNU/Linux" or "GNU/Hurd".  Other people seem to think
     that the kernel is the most important part of the system, so they
     like to call their GNU operating systems "Linux systems."

     I, personally, believe that this is a grave injustice, because the
     _boot loader_ is the most important software of all. I used to
     refer to the above systems as either "LILO"(1) (*note Role of a
     boot loader-Footnote-1::) or "GRUB" systems.

     Unfortunately, nobody ever understood what I was talking about;
     now I just use the word "GNU" as a pseudonym for GRUB.

Обясните. Вот есть:
class S (a :: *) (b :: *) | b -> a
class C (c :: *) 
data T a = T
instance S a b => C (T b)
и инстанс просит UndecidableInstances. 
> Variable occurs more often in a constraint than in the instance head
Но ведь `a' можно однозначно вывести? В чем проблема?

Второй день продолжаются такие глупые попытки как перехитрить природу и написать претти принтер на функторах. По-хорошему принтер это: 
newtype P doc a = P { runP :: a -> doc }; но это контравариантный функтор. Если немного порисовать стрелочки, то можно заметить что выкрутиться можно представив принтер как отношение, добавив недостающую стрелку в обратную сторону. В свою очередь, отношение можно представить как [(a, doc)], то есть получаем: 
newtype P doc a = P { runP :: [(a, doc)] }; теперь все хорошо, есть также необходимые инстансы для Applicative и Alternative, которые можно взять, вообще говоря, из mtl, так как второй вариант есть (WriterT Doc (ListT m) a). За исключением одного очевидного недостатка -- длинна итогового списка; самый неприятный, можно сказать взрыв, происходит в (<*>), ведь length (a <*> b) = length a * length b. Ну и length (a <|> b) = length a + length b, что тоже как-бы.
Inspired by "Invertible Syntax Descriptions: Unifing Parsing and Pretty Printing" хочется все-таки как-то сделать, не смотря на то, что похоже, это невозможно. (Надо наверно попытаться сделать HOAS и свой Doc, может тогда что-то получится)

А менее черезжопного пути, кроме как вводить хелпер, что получить имя promoted типа нет?

    :set -XTemplateHaskell -XDataKinds
    data T = TC
    type Helper = TC
    $(do TyConI (TySynD (ConT tn)) <- reify ''Helper; stringE $ show tn)

":Interactive.TC"

Похоже одинаковая нотация (префикc ') в TH и DataKinds создают немало проблем. Например, есть data T = T;
'T здесь это имя конструктора типа T кайнда ; ''T это имя типа T кайда . Причем получить через ''T имя типа T кайнда T просто не представляется возможным, неоднозначность.
Не говоря о том, что получить имена promoted типов(до кайндов) и конструкторов (до типов) вообще не получается.

> :k '(Int, '(Int, (Char, Int)))
'(Int, '(Int, (Char, Int))) :: (,) * (*, *)
> :k '(Maybe, Just, '[], '[(->) Int, IO, []], Eq, '[MonadReader, MonadWriter])
'(Maybe, Just, '[], '[(->) Int, IO, []], Eq, '[MonadReader, MonadWriter]) :: (,,,,,)
                                                                               (* -> *)
                                                                               (AnyK -> Maybe AnyK)
                                                                               [AnyK]
                                                                               [* -> *]
                                                                               (* -> Constraint)
                                                                               [*
                                                                                -> (* -> *)
                                                                                -> Constraint]

Позиция ErrorT в "стеке" означает какие состояния возможно восстановить после ошибки, а какие нет. Все что вложено можно, а все что снаружи -- нельзя. То есть ErrorT иногда стоит пропихнуть поглубже, чтобы восстанавливать то что стало неактуальным после ошибки, и делать это в catchError соответственно. То есть тут у нас фактически в типе трансформера все явно закодировано, что очень круто получается и вообще удобно.
Ещё есть предположение, что не всегда можно найти правильный порядок трансформеров, то бишь не всегда можно найти именно такой "стек" который нужен. Логика тут такая; пусть есть: 
A, B, (ErrorT SomeError) :: (* -> *) -> * -> *
Необходимо чтобы B было внутри A, но сохранять только A, но не B. Очевидно что такого стека не существует. Но тут надо найти более реалистичный контрпример.

Странный конечно вопрос, но все же. Eсть функция 'mkFun' которая берет имя и что-то ещё и возвращает что-то:
1.     myFunName = mkFun "myFunName" $ somethingElse
Но! Это совсем неудовлетворительно. Во-первых некрасиво, во-вторых нужно следить за уникальность имен, ну и писать руками. Хотелось бы что-нибудь эдакое:
2.     myFunName = mkFun' $ somethingElse
и это раскрывается в (1). Но здесь без TH не обойтись, верно? Или по крайней мере:
myFunName = mkFun'' $ somethingElse
что раскрывается в: 
3.     myFunName = mkFun "generatedUniqueName" $ somethingElse
Но здесь без CPP не обойтись. Идентикатор может быть любого типа, главное чтобы он был уникальным и на нем был определен Eq, а ещё лучше Ord.
Есть ещё вариант затащить это в State и крутить там счетчик, как-то так:
(myFunName1, myFunName2) = runModule "myModuleName" $ do 
    myFunName1 <- mkFun' $ somethingElse 
    myFunName2 <- mkFun' $ somethingElse
    return (myFunName1, myFunName2)
но это совсем несерьезно, тем более нужно опять же именовать модуль и следить за уникальность этих имен. Ну и самая безумная идея, глобальный IORef счетчик...
Так вот, как это сделать по-нормальному?

Что значат .\ в конце функций в отчетах которые рантайм выплевывает с +RTS -p, то бишь в профилировочных отчетах? (странновато звучит) Например: 
 allocNamedColor              Graphics.X11.Xlib.Color
 -allocNamedColor.\           Graphics.X11.Xlib.Color
 --allocNamedColor.\.\        Graphics.X11.Xlib.Color
 ---allocNamedColor.\.\.\     Graphics.X11.Xlib.Color
Похоже на лямбду, но что это? Максимальное количество .\ совпадает с количеством аргументов, стало быть, что-то связанное с частичными применениями. Но что тогда значит:
 wcDrawImageString.\          Graphics.X11.Xlib.Extras
 wcDrawImageString            Graphics.X11.Xlib.Extras
Внимание, тут и тот и тот cost-centre находит на одном уровне, в то время как в первом случае они вложены, причем здесь в обратном порядке. В доках что-то ничего нет по этому поводу, я в замешательстве.

А можно ли что-нибудь наподобие сделать, только чтобы оно работало? Т.е. нужно что-то навроде частичной специализации в С++, класс определен для всех типов, но для некоторых определен по-другому.
class Test a where
  test :: a -> IO ()

instance Num a => Test a where
  test _ = putStrLn "its a num"

instance Test a where
  test _ = putStrLn "its not a num" 
Вот это даже с -XOverlappingInstances не работает.