diff options
author | joe <joe@jerkface.net> | 2014-04-14 02:28:55 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-04-14 02:28:55 -0400 |
commit | fe075ae203a8f8809c7dcf3d7e600679ec5b804b (patch) | |
tree | 4e1e637cb570d66cf501bcdcbb1a0cc7bdbdc6d8 | |
parent | 11eff640b5757048e4323433324afb96553640f0 (diff) |
experimental monad instance
-rw-r--r-- | KeyRing.hs | 140 |
1 files changed, 133 insertions, 7 deletions
@@ -1,6 +1,7 @@ | |||
1 | {-# LANGUAGE CPP #-} | 1 | {-# LANGUAGE CPP #-} |
2 | {-# LANGUAGE TupleSections #-} | 2 | {-# LANGUAGE TupleSections #-} |
3 | {-# LANGUAGE ViewPatterns #-} | 3 | {-# LANGUAGE ViewPatterns #-} |
4 | {-# LANGUAGE ExistentialQuantification #-} | ||
4 | module KeyRing where | 5 | module KeyRing where |
5 | 6 | ||
6 | import System.Environment | 7 | import System.Environment |
@@ -33,7 +34,12 @@ home = HomeDir | |||
33 | , optfile_alts = ["keys.conf","gpg.conf-2","gpg.conf"] | 34 | , optfile_alts = ["keys.conf","gpg.conf-2","gpg.conf"] |
34 | } | 35 | } |
35 | 36 | ||
36 | data InputFile = HomeSec | HomePub | ArgFile FilePath | 37 | data InputFile = HomeSec | HomePub | ArgFile FilePath | FileDesc Int |
38 | |||
39 | data FileType = KeyRingFile | PEMFile | WalletFile | ||
40 | |||
41 | data RefType = ConstRef | MutableRef | ||
42 | |||
37 | 43 | ||
38 | data KeyRingRuntime = KeyRingRuntime | 44 | data KeyRingRuntime = KeyRingRuntime |
39 | { rtPubring :: FilePath | 45 | { rtPubring :: FilePath |
@@ -43,14 +49,17 @@ data KeyRingRuntime = KeyRingRuntime | |||
43 | , rtGrip :: Maybe String | 49 | , rtGrip :: Maybe String |
44 | } | 50 | } |
45 | 51 | ||
52 | data KeyRingAction a = KeyRingAction a | RunTimeAction (KeyRingRuntime -> a) | ||
53 | |||
46 | data KeyRingData a = KeyRingData | 54 | data KeyRingData a = KeyRingData |
47 | { filesToLock :: [InputFile] | 55 | { kFiles :: Map.Map InputFile (RefType,FileType) |
48 | , homeSpec :: Maybe String | 56 | , homeSpec :: Maybe String |
49 | , kaction :: KeyRingRuntime -> IO a | 57 | , kAction :: KeyRingAction a |
50 | , keyringFiles :: [FilePath] | ||
51 | , walletFiles :: [FilePath] | ||
52 | } | 58 | } |
53 | 59 | ||
60 | kret :: a -> KeyRingData a | ||
61 | kret x = KeyRingData Map.empty Nothing (KeyRingAction x) | ||
62 | |||
54 | todo = error "unimplemented" | 63 | todo = error "unimplemented" |
55 | 64 | ||
56 | data KikiCondition a = KikiSuccess a | FailedToLock [FilePath] | 65 | data KikiCondition a = KikiSuccess a | FailedToLock [FilePath] |
@@ -77,6 +86,7 @@ data KikiResult a = KikiResult | |||
77 | , kikiReport :: [ (FilePath, KikiReportAction) ] | 86 | , kikiReport :: [ (FilePath, KikiReportAction) ] |
78 | } | 87 | } |
79 | 88 | ||
89 | {- | ||
80 | empty = KeyRingData { filesToLock = [] | 90 | empty = KeyRingData { filesToLock = [] |
81 | , homeSpec = Nothing | 91 | , homeSpec = Nothing |
82 | , kaction = \KeyRingRuntime {} -> return () | 92 | , kaction = \KeyRingRuntime {} -> return () |
@@ -116,6 +126,7 @@ runKeyRing keyring = do | |||
116 | forM_ lked $ \(Just lk, fname) -> do dotlock_release lk | 126 | forM_ lked $ \(Just lk, fname) -> do dotlock_release lk |
117 | dotlock_destroy lk | 127 | dotlock_destroy lk |
118 | return KikiResult { kikiCondition = ret, kikiReport = [] } | 128 | return KikiResult { kikiCondition = ret, kikiReport = [] } |
129 | -} | ||
119 | 130 | ||
120 | parseOptionFile fname = do | 131 | parseOptionFile fname = do |
121 | xs <- fmap lines (readFile fname) | 132 | xs <- fmap lines (readFile fname) |
@@ -372,10 +383,125 @@ merge_ db filename qs = foldl mergeit db (zip [0..] qs) | |||
372 | mergeSubSig n sig Nothing = error $ | 383 | mergeSubSig n sig Nothing = error $ |
373 | "Unable to merge subkey signature: "++(words (show sig) >>= take 1) | 384 | "Unable to merge subkey signature: "++(words (show sig) >>= take 1) |
374 | 385 | ||
375 | data Kiki a = Kiki | 386 | data Kiki a = SinglePass (KeyRingData a) |
387 | | forall b. MultiPass (KeyRingData b) (Kiki (b -> a)) | ||
388 | |||
389 | instance Functor Kiki where | ||
390 | fmap f (SinglePass d) = SinglePass $ case kAction d of | ||
391 | KeyRingAction v -> d { kAction = KeyRingAction (f v) } | ||
392 | RunTimeAction g -> d { kAction = RunTimeAction (f . g) } | ||
393 | fmap f (MultiPass p k)= MultiPass p (fmap (f .) k) | ||
394 | |||
395 | eval :: KeyRingRuntime -> Kiki a -> a | ||
396 | eval rt (SinglePass (KeyRingData { kAction = KeyRingAction v})) = v | ||
397 | eval rt (SinglePass (KeyRingData { kAction = RunTimeAction f})) = f rt | ||
398 | eval rt (MultiPass p kk) = eval rt kk $ eval rt (SinglePass p) | ||
399 | |||
400 | fmapWithRT :: (KeyRingRuntime -> a -> b) -> Kiki a -> Kiki b | ||
401 | fmapWithRT g (SinglePass d@(KeyRingData { kAction = KeyRingAction v})) | ||
402 | = SinglePass $ d { kAction = RunTimeAction (\rt -> g rt v) } | ||
403 | fmapWithRT g (SinglePass d@(KeyRingData { kAction = RunTimeAction f})) | ||
404 | = SinglePass $ d { kAction = RunTimeAction f' } | ||
405 | where f' rt = g rt (f rt) | ||
406 | fmapWithRT g (MultiPass p kk) = MultiPass p (fmapWithRT g' kk) | ||
407 | where g' rt h = g rt . h | ||
408 | |||
409 | kjoin :: Kiki (Kiki a) -> Kiki a | ||
410 | kjoin k = fmapWithRT eval k | ||
411 | |||
412 | passCount :: Kiki a -> Int | ||
413 | passCount (MultiPass _ k) = 1 + passCount k | ||
414 | passCount (SinglePass {}) = 1 | ||
415 | |||
416 | instance Monad Kiki where | ||
417 | return x = SinglePass (kret x) | ||
418 | k >>= f = kjoin (fmap f k) | ||
419 | |||
420 | {- | ||
421 | kjoin :: Kiki (Kiki a) -> Kiki a | ||
422 | kjoin (SinglePass d) = | ||
423 | case kAction d of | ||
424 | KeyRingAction v -> v | ||
425 | RunTimeAction g -> SinglePass (d { kAction = RunTimeAction g' }) | ||
426 | where g' rt = eval rt (g rt) | ||
427 | |||
428 | kjoin (MultiPass p k)= MultiPass p (fmapWithRT f k) | ||
429 | where | ||
430 | {- | ||
431 | k' = case k of | ||
432 | SinglePass (d { kAction | ||
433 | k :: Kiki (b -> Kiki a) | ||
434 | k' :: Kiki (b -> a) | ||
435 | -} | ||
436 | {- | ||
437 | f :: (b->Kiki a) -> Kiki (b -> a) | ||
438 | f g = SinglePass (p { kAction = RunTimeAction g' }) | ||
439 | where g' rt = \b -> eval rt (g b) | ||
440 | -} | ||
441 | f :: KeyRingRuntime -> (b->Kiki a) -> (b -> a) | ||
442 | f rt g b = eval rt (g b) | ||
443 | -} | ||
444 | |||
445 | |||
446 | ktrav :: Kiki (x -> y) -> x -> Kiki y | ||
447 | ktrav (SinglePass kk) x = SinglePass $ case kAction kk of KeyRingAction f -> kk { kAction = KeyRingAction (f x) } | ||
448 | |||
449 | {- | ||
450 | instance Monad Kiki where | ||
451 | return x = SinglePass (kret x) | ||
452 | |||
453 | kiki >>= f | ||
454 | = join (fmap f kiki) | ||
455 | where | ||
456 | join (SinglePass kd) = | ||
457 | case kAction kd of | ||
458 | KeyRingAction kiki -> kiki | ||
459 | RunTimeAction g -> | ||
460 | let go rt = case g rt of | ||
461 | SinglePass q -> todo | ||
462 | in SinglePass (kd { kAction = RunTimeAction go }) | ||
463 | join (MultiPass x y) = MultiPass x (join y) | ||
464 | -} | ||
465 | |||
466 | |||
467 | {- | ||
468 | data Kiki a = SinglePass (KeyRingData a) | ||
469 | | MultiPass (KeyRingData (Kiki a)) | ||
470 | lastPass :: Kiki a -> KeyRingRuntime -> KeyRingData a | ||
471 | lastPass (SinglePass d) rt = d | ||
472 | lastPass (MultiPass k) rt = case kAction k of | ||
473 | KeyRingAction v -> lastPass v rt | ||
474 | RunTimeAction f -> lastPass (f rt) rt | ||
475 | |||
476 | instance Monad Kiki where | ||
477 | return x = SinglePass (kret x) | ||
478 | SinglePass (kd@(KeyRingData { kAction = KeyRingAction x })) >>= f | ||
479 | = f x | ||
480 | SinglePass (kd@(KeyRingData { kAction = RunTimeAction g })) >>= f | ||
481 | = SinglePass (kd { kAction = RunTimeAction g' }) | ||
482 | where | ||
483 | g' rt = case f (g rt) of | ||
484 | SinglePass d -> | ||
485 | case kAction d of | ||
486 | KeyRingAction y -> y | ||
487 | RunTimeAction h -> h rt | ||
488 | {- | ||
489 | MultiPass d -> | ||
490 | case kAction d of | ||
491 | KeyRingAction k' -> k' >>= f | ||
492 | -} | ||
493 | |||
494 | runKiki :: KeyRingRuntime -> Kiki a -> a | ||
495 | runKiki = todo | ||
496 | -} | ||
497 | |||
498 | -- Kiki a -> a -> Kiki b | ||
499 | |||
500 | atRuntime :: (KeyRingRuntime -> IO (a,KeyRingRuntime)) -> Kiki a | ||
501 | atRuntime = todo | ||
376 | 502 | ||
377 | goHome :: Maybe FilePath -> Kiki () | 503 | goHome :: Maybe FilePath -> Kiki () |
378 | goHome = todo | 504 | goHome p = SinglePass $ (kret ()) { homeSpec = p } |
379 | 505 | ||
380 | syncRing :: InputFile -> Kiki () | 506 | syncRing :: InputFile -> Kiki () |
381 | syncRing = todo | 507 | syncRing = todo |