to post messages and comments.

← All posts tagged code

import Data.Proxy
import Data.Kind

type family Saturate (f :: k) (v :: a) :: Type where
    Saturate (f :: a -> Type) v = f v
    Saturate (f :: a -> k)    v = Saturate (f v) v

data Select f = Select (forall a. Saturate f a -> a)

sel :: Proxy f -> (forall a. Saturate f a -> a) -> Select f
sel _ = Select

data T a b c = T { x :: a, y :: b, z :: c }

Есть такой кусочек кода. Всё как всегда:
Select x — реджектится компилятором (без явной аннотации типа) потому что из Saturate f a нельзя вывести f.
sel x — работает, но таскать Proxy (или явную аппликацию типа) не хочется.
Есть шанс сделать красиво?

В догонку к #2862204

isDiscard :: AnException -> Bool
(discard, isDiscard) = (E.throw (E.ErrorCall msg), isDiscard)
 where
  msg = "DISCARD. " ++
        "You should not see this exception, it is internal to QuickCheck."
  isDiscard e =
    case E.fromException e of
      Just (E.ErrorCall msg') -> msg' == msg
      _ -> False

Ну вот примерно так всё там внутри и выглядит.

Господа java-программисты, по этому бэктрейсу можно сказать чего не хватает этому куску говна скомпилированному в 2014ом году?

ERROR: Uncaught Exception: java.lang.ExceptionInInitializerError
        at com.bric.swing.QDialog.createOKButton(Unknown Source)
        at com.bric.swing.QDialog.createDialogFooter(Unknown Source)
        at com.bric.swing.QDialog.showDialog(Unknown Source)
        at com.bric.swing.QDialog.showDialog(Unknown Source)
        at com.treestar.lib.dialogs.SDialogs.notify(Unknown Source)
        at com.treestar.lib.dialogs.SDialogs.notify(Unknown Source)
        at com.treestar.lib.dialogs.SDialogs.notify(Unknown Source)
        at com.treestar.flowjo.main.Main.javaCheck(Unknown Source)
        at com.treestar.flowjo.main.Main.initMain(Unknown Source)
        at com.treestar.flowjo.main.Main.main(Unknown Source)
Caused by: java.lang.NullPointerException
        at com.treestar.lib.FJCommand.<clinit>(Unknown Source)
        ... 10 more

Нет, исходников у меня нет.

Есть тип data Box (xs :: [*]) where { Box :: (KnownNat n, Elem a xs ~ 'True) => a -> Proxy n -> Box xs }, есть типофамилия что-то вроде ForAll (cxt :: * -> Constraint) (xs :: [*]), которая конструирует констрейнт путём применения cxt ко всем типам в списке xs. Теперь я хочу функцию вида withBox :: ForAll cxt xs => Proxy cxt -> Box xs -> (forall a. cxt a => a -> t) -> t, которая будет применять функцию про констрейнт к содержимому коробки при условии, что для всех возможных вариантов содержимого коробки констрейнт определён.

У меня тут регионопроблемы. Пусть у меня есть функции вида:

doWith :: Shit res -> (forall s. res s -> Reg s ()) -> IO ()

traverseRes :: (Generic (res s), Magic (Rep (res s))) => res s -> Reg s ()

По отдельности всё хорошо, но если сделать что-то вроде:

\hnd -> doWith hnd traverseRes

Незамедлительно наступает ад, поскольку функции очень нужен констрейнт от traverseRes, но s уже стёрто и задать его никак нельзя. Собственно два вопроса: можно ли как-то убедить компилятор что констрейнты справедливы для любого s и как с этим борются при использовании регионов здорового человека?

Я не помню какое звукоподражание в такой ситуации выдаёт @qnikst.

λ> :set -XApplicativeDo 
λ> :t do x <- pure True; return (if x then Nothing else Just x) 
do x <- pure True; return (if x then Nothing else Just x)
  :: Applicative f => f (Maybe Bool)
λ> :t do x <- pure True; return $ if x then Nothing else Just x 
do x <- pure True; return $ if x then Nothing else Just x
  :: Monad m => m (Maybe Bool)

Это баг или фича? Ну и на закуску:

λ> :t do x <- return  True; return  (if x then Nothing else Just x) 
do x <- return  True; return  (if x then Nothing else Just x)
  :: Monad f => f (Maybe Bool)

Есть список. Хочу tails с сигнатурой [a] -> [NonEmpty a]. В лоб это делается примерно так:

catMaybes . fmap nonEmpty . tails

Но это нужно сделать кучу (три) импоротов из них многие (два) содержат коллизии имён. И вообще оно как-то слишком поняно. Неужели FT-магия не спасёт меня?

Есть у меня тупофамилия вида:

type family T t :: (* -> *) -> * -> *

и тип вида

newtype A t m a = A (T t m a)

Можно как-нибудь прибить к типофамилии констрейнт, который постулирует что получается MonadTrans, а T t m — вообще монада. Очень надоело это писать в сигнатурах функций.

Положим у есть тип:

data T cxt t = forall m. cxt (m :: * -> *) => T (t m ())

Теперь можно конструировать типы вида:

undefined :: T Monad ListT

Внимание вопрос: как сконструировать констрейнт из двух классов и передать его в качестве параметра? Или одна переменная, одна нация, один словарь?

class MonadTrans t => Injectable t where
    injection :: (Monad m, MonadTrans k) => (forall n a. Monad n => k n a -> n a) -> t (k m) b -> t m b

Это достаточно безопасный интерфейс чтобы пропихивать на дно стека новый трансформер и при этом не быть форкнутым?

Задумался что в контексте monad remote имеет смысл специальный класс OnException с одноименным методом таким что для любых двух buffered команд справедливо:

(cmd1 `onException` hnd1) <*> (cmd2 `onException` hnd2) == (cmd1 <*> cmd2) `onException` (hnd1 >> hnd2)

Правда форкать exceptions так не хочется. Также никак не пойму кто кому суперкласс: OnException для MonadCatch или наоборот.