← All posts tagged ЖЖ

kb

Драйвер редиса возвращает `Redis (Either Reply a)`. При операции `HGET` возвращает, соответственно, `Redis (Either Reply (Maybe ByteString))`, типа значения по ключу может и не быть. Программист для упрощения пишет сначала специальную функцию `redis'`, которая заворачивает ответ редиса в EitherT-based монаду, чтоб соединять подобные вычисления и возвращать первую неудачу:

```
newtype Redis' a = Redis' (EitherT Redis.Reply Redis.Redis a) deriving (MonadIO)
instance Monad Redis' where
    return = Redis' . EitherT . return . Right
    (Redis' m) >>= f = Redis' $ m >>= \rv -> unwrapRedis' $ f rv
redis' = Redis' . EitherT
```

Таким образом, теперь, если вы получаете ответ `Redis (Either Reply a)`, вы его преобразуете в

```
Redis' (EitherT Reply Redis a)
```

и можете соединять подобные вычисления в do-блоке типа:

```
do
    res <- redis' $ Redis.hget foo bar
    res2 <- redis' $ Redis.hget baz zab
```

и вычисление остановится на первом возврате ошибки.

Далее. Программисту необходимо по кучке значений сделать `HGET` и вернуть это как-то внутри кортежа, поскольку мы внутри новой монады `Redis'` -- завернуть результат в неё. В случае, если значения хоть по одному ключу не существует, хочется вернуть `Nothing` для всех. Потому создаётся новая монада:

```
newtype HashFields a = HashFields (MaybeT Redis' a)
    deriving (Functor, Monad)
instance Applicative HashFields where
    pure = return
    (<*>) = ap
```

описывающая вычисления типа `Redis'`, которые могут вернуть неудачу. Пишется новая функция

```
hashField = HashFields . MaybeT . redis'
```

способная завернуть результат неудачи в новую монаду, которая умеет останавливаться на первой неудаче. Также пишется специальная функция для `HGET`:

```
getField :: ByteString -- ^ Key
         -> ByteString -- ^ Hash field name
         -> HashFields String
getField key field = fmap toString $ hashField $ Redis.hget key field
```

Также напишем функцию, которая "запустит" наше вычисление:

```
getRedisFields :: forall a. HashFields a -> Redis' (Maybe a)
getRedisFields (HashFields f) = runMaybeT f
```

И теперь лёгким движением руки мы можем сделать что-то вроде:

```
getRedisFields ((,,,,,) <$>
    getField k "foo" <*>
    getField k "bar" <*>
    getField k "baz" <*>
    getField k "zab" <*>
    getField k "rab" <*>
    getField k "oof")
```

Вопрос: вам не кажется это "слишком"? Я пока еще не настолько просто манипулирую типами в голове, чтоб ощутить всю ситуацию, хорошо хоть в целом могу медленно прости по шагам по коду, но есть ощущение, что что-то здесь не так.

kb

Пишу тонну factory-бойлерплейта, но понимаю, что читающий может быть
слишком шокирован, потому заставляю себя "пока-что-ненужные" вещи
писать напрямую. Possible-cultural-misunderstanding-driven
development.

kb

Тот самый момент, когда риак-нода уже день как лежит, а никого рядом нет, чтоб поднять, и ничего страшного (по идее, хотя не уверен, т.к. настройки-то можно накрутить там почти какие угодно).

kb

Интересно, насколько глупой является идея перенести всю музыкальную деятельность (чтоб в т.ч. записывать миди всякие там) в виртуальную машину?

kb

Мда. Думал, у меня крыша начала ехать, когда хаскельный

λ> show date
2013-09-12 09:57:21.443007 UTC

В БД ложился как

2013-09-12 09:57:21.443 UTC

Оказалось, в ECMAScript жёстко прописаны миллисекунды, и сериализация в JSON режет.

kb

Постепенно учусь пользоваться тегами. Умею уже их генерировать (тут с х-лем всё сложновато как-то), ходить по ним (M-.), и даже ходить обратно (M-*). До чего техника дошла!

kb

Классика. Нарасставлял кучу трейсов и прочей фигни, потратил ~30 минут. А всё для того, чтобы понять, что у меня в assertEqual неправильные данные ожидаются.

kb

Прочёл на выходных "Clean Coder" Мартина (вместо Clean Code, случайно). Так быстро я книги по около-программированию еще не читал никогда (240 страниц за два небольших присеста). Конечно, молодец дядька, но вместо чтения книги я бы посоветовал просто глянуть два его спича на railscon (есть на ютубе). Одно, кажется, "What Killed Smalltalk and Can Kill Ruby", а другое — "Architecture the Lost Years".

kb

Сильно ускорил емакс (открытие файлов), отключив хуки vc-плагинов ненужные (типа показа бранча текущего файла и т.п.)

(require 'vc)
(eval-after-load "vc" '(remove-hook 'find-file-hooks 'vc-find-file-hook))

kb

Мда. Чтоб пойти в амазон сказали что дадут тестовое задание на час. Ну я сидел ждал назначенного времени. И тут приходит задание:

— Provide one solution written in C, C++, Java or C#.
WUT? И тут я начинаю качать/устанавливать джаву, гуглить как в ней импорты работают, как из файла числа прочитать, как по классу на файл делать, ломаю мозг заворачиванием функций в классы. Потом как ArrayList склонировать (оказывается, не так просто). Короче туда-сюда и 40 минут потратил на ИНФРАСТРУКТУРУ.

Сволочи, короче. Нет чтоб предупредить, я бы заранее этим занимался.

kb

21 октября 2011 года создал тикет, где просил "побольше монитор", сегодня мне его дали (точнее, монитор я сам нашёл где взять, но ждал пока к нему купят hdmi-шнурок, потому он всё это время стоял без дела). ура!

kb

Блин, вот казалось бы, всего одна сущность (но новая), а я создал на неё целое ПРИЛОЖЕНИЕ (django). Прошёл всего день, а я уже просто счастлив что поступил именно так (а не тупо впихнул её куда-то). Уже пухнет и бизнес-логика и всё остальное. ^_____^

kb

Вообще, у всех этих муз. сервисом хочется интеграции с ласт.фм полной (типа вот вам рекомендуют и т.п.), а не только скробблинга. Круто ведь было бы.

kb

В следующий раз, когда мне нужно будет в базе данных что-то вроде алгебраических типов, лучше я придумаю как это всё запихать в одну табличку и потом автоматически буду разруливать при выборке, чем буду снова мучаться с базовой табличкой и связями к остальным. Настолько сильно всё усложняют, что аж злость берёт.