Available formats: content-negotiated html turtle (see SIOC for the vocabulary)
Back to channel and daily index: content-negotiated html turtle
These logs are provided as an experiment in indexing discussions using IRCHub.py, Irc2RDF.hs, and SIOC.
| 00:00:07 | <mmorrow> | ACTION gives up trying to figure out the flow from the asm |
| 00:00:10 | <TomMD> | I guess that tells me there isn't any other solid info on the web when IRC logs dominate the first page. |
| 00:00:12 | <mmorrow> | too many indirect jumps |
| 00:01:10 | <shapr> | TomMD: Can't argue with that. |
| 00:03:01 | <dibblego> | @type [minBound..maxBound] -- is this in the standard library? |
| 00:03:03 | <lambdabot> | forall a. (Bounded a, Enum a) => [a] |
| 00:03:07 | <dibblego> | @hoogle (Bounded a, Enum a) => [a] |
| 00:03:08 | <lambdabot> | Prelude enumFrom :: Enum a => a -> [a] |
| 00:03:08 | <lambdabot> | Prelude maxBound :: Bounded a => a |
| 00:03:08 | <lambdabot> | Prelude minBound :: Bounded a => a |
| 00:04:15 | <mmorrow> | oh, maybe that "took" isn't getting stuff unboxed since it's just that single function in its own module, so nothing can be specialized |
| 00:04:46 | <dolio> | Yeah. |
| 00:04:46 | <mmorrow> | preflex: zdec ghczmprim_GHCziTypes_ZC_con_info |
| 00:04:47 | <preflex> | ghc-prim_GHC.Types_:_con_info |
| 00:07:56 | <iop> | ah i see |
| 00:08:18 | <iop> | read 00229 ::Int obv drops the zeros |
| 00:09:01 | <iop> | is there a function: f :: String -> [Char] ? |
| 00:09:16 | <TomMD> | iop: id |
| 00:09:24 | <TomMD> | :-) |
| 00:09:39 | <ksf_> | String _is_ [Char]] |
| 00:09:51 | <TomMD> | hence 'id' will work fine. |
| 00:15:55 | <iop> | i have a String and want to turn each char to an int |
| 00:16:02 | <iop> | String -> [Int] |
| 00:16:06 | <iop> | how? |
| 00:16:17 | <iop> | > map (\x -> read x :: Int) "123" |
| 00:16:18 | <lambdabot> | Couldn't match expected type `[GHC.Types.Char]' |
| 00:16:31 | <ziman> | > map digitToInt "123" |
| 00:16:33 | <lambdabot> | [1,2,3] |
| 00:16:34 | <skorpan> | @hoogle Integer -> Char |
| 00:16:35 | <lambdabot> | Prelude fromInteger :: Num a => Integer -> a |
| 00:16:35 | <lambdabot> | Unsafe.Coerce unsafeCoerce :: a -> b |
| 00:16:35 | <lambdabot> | Prelude show :: Show a => a -> String |
| 00:16:49 | <skorpan> | @hoogle Char -> Integer |
| 00:16:50 | <lambdabot> | Unsafe.Coerce unsafeCoerce :: a -> b |
| 00:16:50 | <lambdabot> | Prelude floatRadix :: RealFloat a => a -> Integer |
| 00:16:50 | <lambdabot> | Prelude toInteger :: Integral a => a -> Integer |
| 00:16:58 | <skorpan> | ah, unsafeCoerce, there we have it |
| 00:17:00 | <ziman> | > map ord "123" |
| 00:17:02 | <lambdabot> | [49,50,51] |
| 00:17:10 | <ksf_> | showDecimal n = showIntAtBase 10 intToDigit n "" |
| 00:17:15 | <ziman> | > unsafeCoerce 0 :: String |
| 00:17:17 | <lambdabot> | Not in scope: `unsafeCoerce' |
| 00:17:25 | <centrinia> | > map (chr. ord) "Hello World!" |
| 00:17:27 | <lambdabot> | "Hello World!" |
| 00:17:29 | <ksf_> | ah, we alrealy have a string |
| 00:17:45 | <skorpan> | > map ((-(ord '0')) . ord) "123" |
| 00:17:47 | <lambdabot> | Couldn't match expected type `b -> c' |
| 00:17:49 | <skorpan> | bah |
| 00:19:14 | <iop_> | > map digitToInt "123" |
| 00:19:16 | <lambdabot> | [1,2,3] |
| 00:19:29 | <iop_> | @index digitToInt |
| 00:19:29 | <lambdabot> | Data.Char |
| 00:20:04 | <iop_> | @src digitToInt |
| 00:20:04 | <lambdabot> | Source not found. And you call yourself a Rocket Scientist! |
| 00:20:26 | <ksf_> | :t (-(1)) |
| 00:20:28 | <lambdabot> | forall a. (Num a) => a |
| 00:20:42 | <ksf_> | hmmm... shouldn't that be a (-) section? |
| 00:21:24 | <amz> | > map (-(1)) [1..5] |
| 00:21:25 | <lambdabot> | No instance for (GHC.Num.Num (a -> b)) |
| 00:21:25 | <lambdabot> | arising from a use of syntactic n... |
| 00:21:59 | <amz> | guess that it's simply interpreting it as -1 |
| 00:22:15 | <amz> | > map ((-)1) [1..5] |
| 00:22:17 | <lambdabot> | [0,-1,-2,-3,-4] |
| 00:22:28 | <amz> | meh |
| 00:22:33 | <twanvl> | > map (subtract 1) [1..5] |
| 00:22:34 | <lambdabot> | [0,1,2,3,4] |
| 00:25:44 | <jimmyjazz14> | map (+) 7) [1..10] |
| 00:25:58 | <jimmyjazz14> | map ((+) 7) [1..10] |
| 00:26:24 | <jimmyjazz14> | lambdabot: :t map |
| 00:26:34 | <jimmyjazz14> | lambdabot: help |
| 00:26:43 | <shapr> | @help |
| 00:26:43 | <lambdabot> | help <command>. Ask for help for <command>. Try 'list' for all commands |
| 00:26:52 | <shapr> | > map (+ 7) [1..10] |
| 00:26:53 | <lambdabot> | [8,9,10,11,12,13,14,15,16,17] |
| 00:27:40 | <jimmyjazz14> | > map ((+) 4) [1..20] |
| 00:27:41 | <lambdabot> | [5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] |
| 00:27:42 | <shapr> | jimmyjazz14: Do you have ghci installed? Many things that work in ghci will work if you put them after > here on #haskell |
| 00:27:51 | <jimmyjazz14> | heh cool |
| 00:27:53 | <shapr> | :t (+ 4) |
| 00:27:54 | <lambdabot> | forall a. (Num a) => a -> a |
| 00:28:14 | <jimmyjazz14> | :t map |
| 00:28:15 | <lambdabot> | forall a b. (a -> b) -> [a] -> [b] |
| 00:29:20 | <shapr> | :t \a b -> b a |
| 00:29:21 | <lambdabot> | forall t t1. t -> (t -> t1) -> t1 |
| 00:29:29 | <jimmyjazz14> | I've been trying to get lambdabot to run on Arch |
| 00:29:39 | <jimmyjazz14> | anyone got that going? |
| 00:29:41 | <shapr> | Not working? |
| 00:29:48 | <shapr> | I haven't tried to build lambdabot recently. |
| 00:29:56 | <sjanssen> | jimmyjazz14: getting lambdabot to build is always a bit of a chore |
| 00:30:55 | <jimmyjazz14> | I was trying to do it with AUR |
| 00:31:13 | <jimmyjazz14> | I get dependency problems with haskell-brainfuck |
| 00:31:28 | <shapr> | I use debian, I assume AUR is the package management system for Arch? |
| 00:31:49 | <jimmyjazz14> | yeah |
| 00:31:55 | <skorpan> | shapr: the user repo stuff |
| 00:32:05 | <jimmyjazz14> | kinda |
| 00:32:05 | <shapr> | oh |
| 00:32:29 | <skorpan> | jimmyjazz14: i think you're just better off cabal installing everything haskellish |
| 00:32:43 | <skorpan> | the AUR has bitten me so many times and cabal mostly works better |
| 00:32:43 | <jimmyjazz14> | yeah I'll probably just do that |
| 00:32:53 | <skorpan> | i never use the AUR for haskell packages anymore |
| 00:33:12 | <jimmyjazz14> | yeah its been a bit of a pain for me |
| 00:34:04 | <iop_> | how do I convert from Int to Double? apparently fromIntegral fosnt do that |
| 00:35:38 | <sjanssen> | iop_: fromIntegral does do that |
| 00:35:45 | <sjanssen> | > fromIntegral (1 :: Int) :: Double |
| 00:35:46 | <amz> | > (fromInteger 5) :: Double |
| 00:35:47 | <lambdabot> | 1.0 |
| 00:35:48 | <lambdabot> | 5.0 |
| 00:37:19 | <skorpan> | :t fromIntegral |
| 00:37:20 | <lambdabot> | forall a b. (Integral a, Num b) => a -> b |
| 00:37:36 | <skorpan> | :t fromInteger |
| 00:37:38 | <lambdabot> | forall a. (Num a) => Integer -> a |
| 00:37:51 | <skorpan> | so, basically there is no point in using fromInteger as opposed to fromIntegral? |
| 00:38:42 | <jbauman> | > (fromIntegral 1) :: Double |
| 00:38:43 | <lambdabot> | 1.0 |
| 00:38:57 | <skorpan> | ...is there? |
| 00:39:37 | <Cale> | skorpan: It's important when defining Num instances, and that's about it. |
| 00:39:46 | <skorpan> | how so? |
| 00:39:51 | <mmorrow> | in ghc fromIntegral is implemented with {-# RULES ... #-} for all the types, so it's guaranteed to be the most efficient possible way |
| 00:40:25 | <Cale> | Because fromInteger is a method of the Num class which is responsible for the interpretation of integer literals. |
| 00:40:45 | <Cale> | But other than that, fromIntegral is usually more convenient. |
| 00:41:36 | <mmorrow> | skorpan: yeah, fromInteger is what implicitly happens with all integer literals |
| 00:41:55 | <mmorrow> | 1 :: Tree (Maybe (Either (Map () ()) Int)) |
| 00:42:00 | <mmorrow> | ==> fromInteger 1 |
| 00:42:05 | <Cale> | When you write 5435789341075439, the compiler desugars that to fromInteger (5435789341075439 :: Integer) |
| 00:42:33 | <skorpan> | Cale: why is ":: Integer" necessary? |
| 00:42:49 | <dolio> | It isn't. |
| 00:42:53 | <mmorrow> | i think he was just to being explicit |
| 00:42:58 | <skorpan> | oh |
| 00:43:06 | <Cale> | I was just being explicit that it's *actually* an integer there |
| 00:43:30 | <skorpan> | okay, so it does fromInteger... but what is the result type? |
| 00:43:32 | <Cale> | (and not another polymorphic integer literal, because that would be silly) |
| 00:43:32 | <skorpan> | Num a? |
| 00:43:36 | <Cale> | yeah |
| 00:43:47 | <Cale> | :t 5 |
| 00:43:49 | <lambdabot> | forall t. (Num t) => t |
| 00:43:58 | <skorpan> | i see |
| 00:44:00 | <mmorrow> | > 1 :: Tree (Maybe (Either (Either () ()) Int)) |
| 00:44:01 | <lambdabot> | No instance for (GHC.Num.Num |
| 00:44:01 | <lambdabot> | (Data.Tree.Tree |
| 00:44:01 | <lambdabot> | ... |
| 00:44:06 | <skorpan> | :t fromInteger (2434 :: Integer) |
| 00:44:08 | <lambdabot> | forall a. (Num a) => a |
| 00:44:30 | <skorpan> | :t Tree |
| 00:44:32 | <lambdabot> | Not in scope: data constructor `Tree' |
| 00:44:53 | <skorpan> | does lambdabot have any "builtin" natural number type? |
| 00:45:12 | <skorpan> | as in something like data Nat = Succ Nat | Zero |
| 00:45:28 | <mmorrow> | data E = Lit Integer | E :+ E | E :* E deriving(Eq,Ord,Read,Show); instance Num E where fromInteger = Lit; (+) = (:+); (*) = (:*); signum = undefined; abs = undefined |
| 00:45:44 | <mmorrow> | , src ''Tree |
| 00:45:47 | <lunabot> | data Tree a = Node {rootLabel :: a, subForest :: (Forest a)} |
| 00:46:04 | <shepheb> | having a parsec issue. I've got a parser for variable declarations, and another for statements. the parser for a procedure expects variable declarations followed by statements, but it fails in the vardecls one, on the first statement. it's like it doesn't backtrack far enough. |
| 00:46:52 | <mmorrow> | shepheb: are you using 'try' enough? parsec does depth-first search, so once it commits to a subtree without try, it never looks back |
| 00:47:05 | <shepheb> | possibly not. |
| 00:47:06 | <mauke> | o/` if at first you don't succeed ... o/` |
| 00:47:19 | <skorpan> | the lesson is "never try" |
| 00:47:23 | <Botje> | .. get a bigger gun? |
| 00:47:33 | <mmorrow> | .. cheat? |
| 00:47:53 | <Botje> | .oO(aimbots written in haskell) |
| 00:48:08 | <Twey> | ACTION laughs. |
| 00:48:35 | <skorpan> | :t Nat |
| 00:48:37 | <lambdabot> | Not in scope: data constructor `Nat' |
| 00:48:49 | <skorpan> | so lambdabot does *not* have any builtin natural number type? |
| 00:49:54 | <roconnor> | > 1 : Natural |
| 00:49:55 | <lambdabot> | Not in scope: data constructor `Natural' |
| 00:50:08 | <roconnor> | > 1 :: Natural |
| 00:50:09 | <lambdabot> | 1 |
| 00:50:23 | <skorpan> | @src Natural |
| 00:50:23 | <lambdabot> | Source not found. My mind is going. I can feel it. |
| 00:50:28 | <skorpan> | hm... |
| 00:50:37 | <roconnor> | > infinity :: Natural |
| 00:50:39 | <lambdabot> | * Exception: stack overflow |
| 00:50:44 | <skorpan> | > (1 :: Natural) - (2 :: Natural) |
| 00:50:46 | <lambdabot> | * Exception: Natural: (-) |
| 00:50:53 | <skorpan> | > (1 :: Natural) - (1 :: Natural) |
| 00:50:54 | <lambdabot> | 0 |
| 00:51:11 | <skorpan> | > fromIntegral (1 :: Natural) :: Integer |
| 00:51:12 | <lambdabot> | 1 |
| 00:51:18 | <skorpan> | > fromIntegral (1 :: Natural) |
| 00:51:20 | <lambdabot> | 1 |
| 00:51:24 | <skorpan> | > :t fromIntegral (1 :: Natural) |
| 00:51:26 | <lambdabot> | <no location info>: parse error on input `:' |
| 00:51:30 | <skorpan> | :t fromIntegral (1 :: Natural) |
| 00:51:31 | <lambdabot> | forall b. (Num b) => b |
| 00:52:40 | <skorpan> | > (1383148184848 :: Natural) - (1 :: Natural) |
| 00:52:44 | <lambdabot> | * Exception: stack overflow |
| 00:52:48 | <skorpan> | > (1383148184 :: Natural) - (1 :: Natural) |
| 00:52:51 | <lambdabot> | * Exception: stack overflow |
| 00:52:53 | <skorpan> | > (1383148 :: Natural) - (1 :: Natural) |
| 00:52:56 | <lambdabot> | * Exception: stack overflow |
| 00:52:58 | <skorpan> | > (1383 :: Natural) - (1 :: Natural) |
| 00:53:00 | <lambdabot> | 1382 |
| 00:53:05 | <skorpan> | there we are |
| 00:53:44 | <skorpan> | > (1383 :: Natural) - (1 :: Integer) |
| 00:53:45 | <lambdabot> | Couldn't match expected type `Data.Number.Natural.Natural' |
| 00:53:58 | <skorpan> | :t (-) |
| 00:53:59 | <lambdabot> | forall a. (Num a) => a -> a -> a |
| 00:54:07 | <skorpan> | ah |
| 00:54:51 | <BMeph> | Hello, everyone. (Back from my stay-cation.) |
| 01:05:00 | <chessguy> | so i've been thinking a lot lately about building a chess strategy DSL |
| 01:05:36 | <chessguy> | my thinking is that i can define very simple engines |
| 01:05:57 | <chessguy> | and then combinators which take 2 (or maybe even more) engines, and create another engine |
| 01:06:03 | <mightybyte> | How will you compose those engines? |
| 01:06:12 | <chessguy> | oh pipe down, you :) |
| 01:06:35 | <chessguy> | haha, i was boring mightybyte with these ideas all day |
| 01:07:16 | <skorpan> | chessguy: you're being pretty abstract right now :P |
| 01:07:55 | <mightybyte> | The worst thing is not the boringness...it's that he's not using haskell. |
| 01:08:29 | <iop> | m = toMatrix "C:/users/saftarn/desktop/sudoku.txt" >>= \r -> return $ fromList $ head r ? |
| 01:08:37 | <chessguy> | i've been re-thinking that, mightybyte |
| 01:08:48 | <mightybyte> | Oh, excellent. |
| 01:08:55 | <skorpan> | :t toMatrix |
| 01:08:57 | <lambdabot> | Not in scope: `toMatrix' |
| 01:09:01 | <skorpan> | oh, uhm... never mind. |
| 01:09:09 | <chessguy> | skorpan: my idea is to sort of have a parsec-like API |
| 01:09:19 | <skorpan> | iop: ... >>= return . fromList . head |
| 01:10:11 | <skorpan> | or maybe ... >>= fromList <$> head, but i'm not sure |
| 01:10:22 | <skorpan> | :t liftM |
| 01:10:24 | <lambdabot> | forall a1 r (m :: * -> *). (Monad m) => (a1 -> r) -> m a1 -> m r |
| 01:10:28 | <sjanssen> | no, fmap (fromList . head) ... |
| 01:10:31 | <skorpan> | no, that doesn't work |
| 01:10:38 | <sjanssen> | or fromList . head <$> ... |
| 01:10:55 | <skorpan> | oh, right |
| 01:12:54 | <skorpan> | :t fmap |
| 01:12:56 | <lambdabot> | forall a b (f :: * -> *). (Functor f) => (a -> b) -> f a -> f b |
| 01:13:06 | <skorpan> | so fmap is just a slightly more general version of liftM, right? |
| 01:13:46 | <chessguy> | mightybyte: i'm back to thinking each engine should just be a function from (Position,LegalMoves) -> Maybe Move |
| 01:13:48 | <skorpan> | hm, no... |
| 01:13:54 | <sjanssen> | liftM is an artifact of some brokenness in the Prelude |
| 01:14:09 | <aavogt> | @hoogle liftM |
| 01:14:10 | <lambdabot> | Control.Monad liftM :: Monad m => (a1 -> r) -> m a1 -> m r |
| 01:14:10 | <lambdabot> | Control.Monad liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r |
| 01:14:10 | <lambdabot> | Control.Monad liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r |
| 01:14:14 | <skorpan> | sjanssen: but what i said isn't true though, is it? because i thought Monad somehow required Functor |
| 01:14:19 | <sjanssen> | skorpan: all monads are functors, but the Prelude classes don't enforce that |
| 01:14:31 | <aavogt> | and its not even in the prelude |
| 01:14:32 | <skorpan> | well, then we sorted that out |
| 01:14:48 | <skorpan> | but how can all monads be functors? |
| 01:15:01 | <sjanssen> | if you've got bind and return: |
| 01:15:03 | <ddarius> | Anyone interested in a decent chunk of a (raw) binding to libusb-1.0 and/or (Haskell) code that talks to Owon oscilloscopes over USB? |
| 01:15:04 | <sjanssen> | @src liftM |
| 01:15:05 | <lambdabot> | liftM f m1 = do { x1 <- m1; return (f x1) } |
| 01:15:58 | <skorpan> | oh... so basically this could hold for any monad: fmap = liftM? |
| 01:16:09 | <roconnor> | yes |
| 01:16:11 | <sjanssen> | yes, that should be true |
| 01:16:32 | <skorpan> | will this prelude brokenness be handled in haskell prime? |
| 01:16:47 | <sjanssen> | probably not |
| 01:16:57 | <sjanssen> | Haskell' isn't very ambitious in that way |
| 01:17:36 | <aavogt> | when did Haskell' start? 1999? |
| 01:17:42 | <dibblego> | it's not? then why bother with Haskell' at all? |
| 01:17:56 | <chessguy> | aavogt: err, try in the 80's sometime, i believe |
| 01:18:03 | <ddarius> | dibblego: Because 1998 was over ten years ago. |
| 01:18:11 | <sjanssen> | aavogt: Haskell' started more recently, 2007 maybe? |
| 01:18:12 | <chessguy> | aavogt: there's a great history of haskell paper out there |
| 01:18:32 | <chessguy> | oh! i mis-read, sorry. missed the "'" |
| 01:18:51 | <skorpan> | heh |
| 01:19:12 | <sjanssen> | dibblego: Haskell' is supposedly an iterative process, with out much backwards incompatible changes |
| 01:19:44 | <sjanssen> | dibblego: but it also hasn't seen too much progress, so who knows what will really come of it |
| 01:19:54 | <kniu> | What's the difference between Text.ParserCombinators.Parsec |
| 01:19:57 | <ddarius> | Well, if anyone is interested in the USB bindings, email me, because I'm not interested in finishing them or maintaining them. |
| 01:19:59 | <kniu> | and Text.Parsec? |
| 01:20:05 | <chessguy> | byorgey: we need some lambdabot love in #haskell-hackphi! |
| 01:20:13 | <ddarius> | Text.Parsec is parsec3 Text.ParserCombinators.Parsec is parsec2 |
| 01:20:18 | <sjanssen> | lambdabot: @join #haskell-hackphi |
| 01:20:32 | <chessguy> | sjanssen: no k in hacphi, sorry |
| 01:20:36 | <sjanssen> | chessguy: you'll need to talk to Cale if you want to make it permanent |
| 01:20:42 | <sjanssen> | lambdabot: @part #haskell-hackphi |
| 01:20:49 | <sjanssen> | lambdabot: @join #haskell-hacphi |
| 01:20:50 | <chessguy> | i ken seplll reel gut |
| 01:20:52 | <kniu> | why have parsec2 installed if you already have parsec3? |
| 01:21:07 | <aavogt> | hmm, there's some mentions of haskell two somewheres, any leads? my searches turn up nothings |
| 01:21:12 | <ddarius> | parsec2 is faster and what most libraries expect. |
| 01:21:23 | <kniu> | huh |
| 01:24:03 | <aavogt> | sjanssen: the mailing list archives for H' go back to 2006 |
| 01:29:56 | <Tsion> | data Integral a => Ratio a = !a :% !a deriving (Eq) |
| 01:30:08 | <Tsion> | What do the !s mean? |
| 01:30:38 | <jaredj> | strictness |
| 01:31:13 | <Tsion> | So it will evaluate them right away? |
| 01:31:33 | <jaredj> | yes, rather than store them as thunks and evaluate them when they're needed. |
| 01:31:48 | <Tsion> | Okay, thanks jaredj |
| 01:34:38 | <Cale> | Tsion: More precisely, anything which evaluates a Ratio value will cause both the fields to be evaluated at that point |
| 01:36:41 | <Cale> | (The report defines it in a slightly different way actually, but I'm fairly sure the difference only matters if you're mixing strict and non-strict fields) |
| 01:38:26 | <sm> | Cale: good evening, fyi I haven't been able to see a speedup with your fast tree builder. I wonder if I lost the benefit by converting it. http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5360#a5360 |
| 01:39:46 | <Cale> | hmm |
| 01:40:28 | <Cale> | Well, I used it at the time to construct some very large trees rather quickly... |
| 01:40:34 | <mmorrow> | ddarius lives |
| 01:41:16 | <Cale> | sm: it looks like you're doing lots of (xs ++ [a]) ? |
| 01:42:06 | <sm> | I guess.. I wanted the full path in each node, not just the node name |
| 01:42:12 | <Cale> | sm: Note that (xs ++ [a]) eventually costs O(length xs) time to evaluate |
| 01:42:25 | <Cale> | and so if you keep doing it, it'll be quadratic time |
| 01:42:29 | <sm> | aha |
| 01:42:34 | <mmorrow> | oh, ddarius has quit |
| 01:42:58 | <sm> | gosh I really need to learn these costs |
| 01:43:50 | <sm> | still, the max length of xs there is the depth of the tree |
| 01:44:14 | <sm> | about 8 |
| 01:44:49 | <sm> | I wish, I wish, for a more readable/friendly profiler |
| 01:45:00 | <Cale> | What does the profiling output say? |
| 01:45:31 | <fracture> | is there a prefered way to put named constants into haskell code? |
| 01:45:37 | <jaredj> | In python, by convention, methods starting with _ are more or less for internal use only. Is there a convention about identifiers starting with _ in Haskell? |
| 01:45:43 | <fracture> | just foo = value maybe? |
| 01:45:48 | <Cale> | fracture: yeah |
| 01:45:56 | <Cale> | fracture: Everything is a named constant anyway ;) |
| 01:45:58 | <fracture> | any naming conventions? |
| 01:46:02 | <fracture> | ah good point |
| 01:46:08 | <fracture> | nm then |
| 01:46:26 | <Cale> | jaredj: Usually that's a hint that the parameter is unused. |
| 01:46:39 | <Cale> | (If it's part of a pattern match) |
| 01:46:48 | <jaredj> | uhh. right, but that's if _ is the whole thing |
| 01:46:53 | <jaredj> | what about _x |
| 01:47:01 | <Cale> | Well, if _ is the whole thing then it *really* is unused |
| 01:47:04 | <jaredj> | sure |
| 01:47:11 | <chessguy> | i've never seen _x as an identifier |
| 01:47:13 | <sm> | Cale: before http://joyful.com/repos/hledger/profs/200905250945.prof , after http://joyful.com/repos/hledger/profs/200905250949.prof |
| 01:47:24 | <jaredj> | wait this whole thing is dumb |
| 01:47:28 | <Cale> | But I've seen the convention where something like _x was used to give a parameter a name even though it goes unused. |
| 01:47:41 | <mmorrow> | sm: ooh, are you making a hierarchical Trie of account (which may have subaccounts which may have..) and then attaching values to the leaves? (i did something very similar at one point) |
| 01:47:46 | <chessguy> | Cale: that's....weird |
| 01:47:51 | <chessguy> | why not just leave it at _ then? |
| 01:47:52 | <jaredj> | if i have a little convenience function needed by two functions i expect others to use, i just don't export it from the module. right? |
| 01:48:07 | <Berengal> | chessguy: Documentation |
| 01:48:09 | <sm> | mmorrow: just a tree, I do not speak trie yet |
| 01:48:26 | <Cale> | jaredj: right |
| 01:48:52 | <jaredj> | ok. thx |
| 01:49:00 | <Cale> | My Tree is effectively a Trie with a large alphabet :) |
| 01:49:28 | <jaredj> | has anyone made a trae yet? |
| 01:49:33 | <mmorrow> | sm: hmm, so are you grouping subaccounts of account underneath their parent account, and so on recursively? |
| 01:49:34 | <sm> | ACTION 's head spins.. steady.. |
| 01:50:02 | <sm> | mmorrow: yes indeed.. I make a tree of account names (the chart of accounts) to start |
| 01:50:10 | <gwern> | jaredj: as a child, I frequently ate off traes |
| 01:50:15 | <sm> | then I transform that into a richer data structure |
| 01:50:28 | <mmorrow> | cool |
| 01:50:35 | <Cale> | sm: hmm... This is the profiling output from the optimised version, yeah? |
| 01:50:40 | <jaredj> | haha |
| 01:51:03 | <sm> | the "after" link is, I'm 98% sure |
| 01:51:06 | <Cale> | The profiling output is harder to read even though it's more accurate when you turn optimisations on. |
| 01:51:08 | <dibblego> | @hoogle Seq a -> [a] |
| 01:51:09 | <lambdabot> | Data.Foldable toList :: Foldable t => t a -> [a] |
| 01:51:09 | <lambdabot> | Prelude repeat :: a -> [a] |
| 01:51:09 | <lambdabot> | Data.List repeat :: a -> [a] |
| 01:51:23 | <Cale> | I'm seeing all these ==_a6iI etc, which are strange. |
| 01:51:34 | <sm> | hmm. I think this profile is unoptimised |
| 01:51:39 | <gwern> | I was very disapointed to find that the Show instance for Seq was 'fromList [...]' |
| 01:51:49 | <Cale> | I'm guessing they're specialisations of equality tests... |
| 01:53:13 | <Cale> | anyway, it looks like in either case, the major time centre is ledgerAccount, and the major allocation centre is isAccountNamePrefixOf |
| 01:53:31 | <Cale> | The latter seems suspicious. |
| 01:53:40 | <Cale> | What does that function look like? |
| 01:53:53 | <Cale> | gwern: What's wrong with that? |
| 01:54:29 | <gwern> | Cale: well, it's inefficient. here we have a strict, finite list, and we're re-using the machinery of regular lists? |
| 01:54:54 | <Cale> | gwern: But it gives you valid Haskell code for reconstructing the list, which is all that it's meant for. |
| 01:55:31 | <gwern> | I know, but we shouldn't need to switch to data.binary every time we need even a tiny bit of performance; the defaults should be reasonably performant |
| 01:55:39 | <Cale> | Huh? |
| 01:55:51 | <Cale> | Lists perform very well for the kind of access which show does. |
| 01:56:30 | <Cale> | In fact, by comparison, Data.Seq would be slower. |
| 01:56:44 | <gwern> | when I was dealing with large Seqs, I noticed data.binary was faster than read/show for seq |
| 01:56:55 | <Cale> | Well, of course. |
| 01:56:58 | <sm> | Cale: it's about a third of the way down http://joyful.com/repos/hledger/Ledger/AccountName.hs |
| 01:58:45 | <dibblego> | is there any way to use two equally named functions from different modules in the same source file without using import qualified? |
| 01:59:10 | <Cale> | sm: Even though it might destroy correctness, will you try something for a moment? Remove that ++ [acctsepchar] |
| 01:59:20 | <sm> | sure thing |
| 02:00:14 | <Cale> | The only way I imagine that function is doing allocation is when it creates that new list. |
| 02:00:49 | <Cale> | Though, I wouldn't expect it to change the time-performance much |
| 02:01:56 | <mauke> | dibblego: yes, just qualify them |
| 02:02:46 | <sm> | Cale: a second slower, but 600M less allocation - http://joyful.com/repos/hledger/profs/200905281900.prof |
| 02:02:58 | <cads> | bleh, currying a variadic function is so ugly |
| 02:03:14 | <Cale> | sm: That's interesting that it would be slower |
| 02:03:54 | <cads> | have to say something like ((curry * 3) 2 4 2 1 :end) => 48 |
| 02:03:58 | <Cale> | sm: anyway, the main cost in time is ledgerAccount, but looking at the code for that, it's probably not ledgerAccount's fault. |
| 02:04:03 | <hatds> | dibblego: no, but if they are highly related functions there might be a way around it |
| 02:04:22 | <Cale> | It's the fact that you're calling it 821149 times... |
| 02:04:24 | <sm> | it's funny I don't see anything under the ledgerAccount 40% line |
| 02:04:26 | <sm> | oh! |
| 02:04:27 | <sm> | that |
| 02:04:34 | <sm> | right you are |
| 02:04:44 | <Cale> | (plus a few) |
| 02:05:01 | <Cale> | and it's all from ledgerAccountTree |
| 02:05:14 | <sm> | isSubAccountNameOf 2 million times |
| 02:06:35 | <Cale> | But apparently that's much cheaper :) |
| 02:06:37 | <sshc> | how do I operator overload in Haskell? |
| 02:07:00 | <Cale> | sshc: Typeclasses |
| 02:07:04 | <sshc> | is it possible to define two functions with the same names but take completely different types of arguments? |
| 02:07:28 | <dibblego> | sshc, yes, using type-classes |
| 02:07:34 | <Cale> | sshc: Yes. You define a typeclass for the set of operations which you want to make general, and then instances for each of the types you want to implement them at |
| 02:07:50 | <Cale> | sm: Where is treemap defined? |
| 02:08:23 | <fracture> | I have a long computation where I want to see what's happening; seems like printf-style debugging is basically impossible in haskell |
| 02:08:29 | <fracture> | is there a way to trace through stuff in ghci? |
| 02:08:35 | <sm> | Cale: http://joyful.com/repos/hledger/Ledger/Utils.hs |
| 02:08:36 | <hatds> | you should also consider whether (say) your 2 functions f1: a1 -> b and f2: a2 -> b are actually representing one function f : a -> b where a is a bigger type |
| 02:08:42 | <aavogt> | @hoogle trace |
| 02:08:42 | <lambdabot> | Debug.Trace trace :: String -> a -> a |
| 02:08:42 | <lambdabot> | module Debug.Trace |
| 02:08:42 | <lambdabot> | package traced |
| 02:08:55 | <Cale> | fracture: Yes, there's a debugger and Debug.Trace.trace |
| 02:09:14 | <fracture> | cool I'll look into that |
| 02:09:15 | <fracture> | thanks |
| 02:09:21 | <Cale> | fracture: But you might find that things happen in a very different order than you expected, if you're not so familiar with lazy evaluation |
| 02:09:32 | <hatds> | fracture: you might find the ghci evaluation stepper more useful than the trace for just understanding how the execution goes |
| 02:09:57 | <dblazakis> | wasn't there a monad reader article on using the ghci debugger? |
| 02:10:02 | <sm> | really.. I found the ghci debugger much more confusing than trace |
| 02:10:24 | <hatds> | sm: meaning, the :step debugging? |
| 02:11:42 | <fracture> | ah yes... the :step output is weird |
| 02:11:46 | <fracture> | I think I need to read the manual for this :) |
| 02:12:50 | <hatds> | Yea, I've never used :step to debug a full fledged program, but I've found it invaluable for learning the finer points about Haskell semantics |
| 02:13:29 | <fracture> | seems like it could be more useful with integration into an editor |
| 02:13:34 | <fracture> | it's cumbersome to type :list every time |
| 02:13:52 | <fracture> | I'll try trace (in other languages I'd most likely printf debug this situation too) |
| 02:14:28 | <hatds> | there's a command to make it :list after every step |
| 02:14:33 | <fracture> | ah |
| 02:14:40 | <hatds> | the ghc user manual has a small tutorial |
| 02:14:50 | <fracture> | :set stop :list |
| 02:14:56 | <fracture> | yay |
| 02:15:01 | <fracture> | ;) |
| 02:15:02 | <sm> | hatds: yeah.. worth learning, but tricksy! It may be a bit better now |
| 02:15:35 | <sm> | it was semi-useful when I tried |
| 02:15:53 | <sm> | peter hercek has been doing cool enhancements |
| 02:17:26 | <kniu> | @src foldl |
| 02:17:27 | <lambdabot> | foldl f z [] = z |
| 02:17:27 | <lambdabot> | foldl f z (x:xs) = foldl f (f z x) xs |
| 02:17:41 | <fracture> | wow this is really neat (seeing how the laziness works) |
| 02:17:57 | <sm> | oh man it's good to be back on the big monitor.. |
| 02:18:54 | <kniu> | @src foldr |
| 02:18:55 | <lambdabot> | foldr f z [] = z |
| 02:18:55 | <lambdabot> | foldr f z (x:xs) = f x (foldr f z xs) |
| 02:27:56 | <iop> | is bitC an ongoing project? |
| 02:28:36 | <sm> | there's something I don't understand in this profile excerpt: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5361#a5361 |
| 02:29:17 | <sm> | is it telling me ledgerAccountTree, called 2457 times, called all of treeprune, ledgerAccount and treemap 800k times ? |
| 02:30:01 | <sm> | and how can that be since it is just: ledgerAccountTree depth l = treemap (ledgerAccount l) $ treeprune depth $ accountnametree l |
| 02:30:35 | <sm> | oh I see.. treemap/treeprune recurse |
| 02:32:12 | <Cale> | There must be a lot of nodes in that tree. |
| 02:32:30 | <sm> | I think I see.. |
| 02:33:15 | <sm> | there are 600 nodes |
| 02:33:38 | <fracture> | hmm |
| 02:33:40 | <sm> | max depth is about 10 |
| 02:33:46 | <fracture> | trying to run the profiler on a program that doesn't terminate |
| 02:33:58 | <fracture> | and the prof file doesn't get anything when I sigint it |
| 02:34:08 | <fracture> | is there any way to do that? |
| 02:34:15 | <sm> | fracture: someone posted recently on-list about a real-time profiler thing |
| 02:34:45 | <fracture> | maybe I can limit my thing to a maximum depth somehow and have it terminate there |
| 02:34:54 | <Cale> | sm: Is it a different tree each time? |
| 02:34:57 | <fracture> | pass an n to my expression and when n > 10000 do an error or something |
| 02:35:01 | <Cale> | sm: Or are you repeating work? |
| 02:35:39 | <sm> | Cale: there's only one tree for the duration of the program.. I guess I must be repeating work somehow |
| 02:35:41 | <gwern> | well, if you're interested in memory, I believe the PS heap profilign output is continuous |
| 02:35:49 | <fracture> | more interested in time |
| 02:36:05 | <fracture> | memory usage seems constant for the program (I think it is GCing everything after it uses it as I proc stuff) |
| 02:36:05 | <Cale> | sm: Perhaps you could compute that treemap higher up and pass the result in? |
| 02:37:11 | <sm> | I don't quite see it |
| 02:37:24 | <sm> | what you mean |
| 02:39:41 | <Cale> | sm: I suppose it's impossible, because it's dependent on l... |
| 02:39:50 | <Cale> | (looking at the code) |
| 02:39:55 | <sm> | I'm not sure why I'm getting this big multiplier effect.. according to me, it does things in stages: first builds the 600-node account name tree; then prunes it; then maps ledgerAccount l to each node |
| 02:40:13 | <Cale> | actually, no, that's not at all what it does |
| 02:41:00 | <Cale> | The first thing to happen is that treemap is applied to (ledgerAccount l), and then that does a pattern match on the tree, which causes treeprune to be evaluated... |
| 02:42:17 | <Cale> | and treeprune also ends up wanting to see the root of the tree, and so accountnametree l is evaluated just enough to construct the root, at which point treeprune matches against it, and then treemap applies the function ledgerAccount l to the root and returns a Branch node. |
| 02:42:31 | <sm> | woah.. rewiring my mental map |
| 02:42:46 | <Cale> | and the treemap and treeprune continue when the subtrees get pattern matched |
| 02:44:24 | <sm> | laziness takes a long time to understand :) |
| 02:45:05 | <sm> | that explanation is a very helpful reminder |
| 02:46:31 | <sm> | then my haskell-sense tells me that I could make something strict here, and it would behave better |
| 02:46:35 | <Cale> | Is there a particular reason you didn't like my way of organising the account names in the tree? |
| 02:46:53 | <sm> | you mean just having the node name at each node ? |
| 02:47:10 | <Cale> | Yeah, and having a Map at each level |
| 02:47:13 | <MyCatVerbs> | sm: meh, laziness. I'll get around to understanding it later, since it's not strictly necessary right away. ;D |
| 02:47:37 | <Cale> | Well, in fact... |
| 02:47:40 | <sm> | Cale: just that it requires rethinking the rest of the app |
| 02:48:03 | <sm> | if I absolutely have to change the whole app to make this perform, I guess I will |
| 02:48:16 | <hackagebot> | HSFFIG 1.1 |
| 02:48:49 | <Cale> | Well, I'm still not certain enough about what this is doing in order to say whether it's necessary/recommendable :) |
| 02:48:58 | <sm> | I mean, it probably won't mean a lot of changes, but a fair bit of thought |
| 02:49:04 | <Cale> | What is it that is being computed here? |
| 02:49:17 | <Cale> | I noticed 'isInteresting' |
| 02:49:56 | <sm> | well, what I've been trying to optimise is just this: |
| 02:49:57 | <sm> | -- | Convert a list of account names to a tree. |
| 02:49:57 | <sm> | accountNameTreeFrom ∷ [AccountName] → Tree AccountName |
| 02:51:07 | <mmorrow> | sm: is an AccountName something like AccountName = (SubAccountName, AccountName) ? |
| 02:51:29 | <sm> | and now I have shifted to understanding why there's such a high multiplier effect |
| 02:51:33 | <Cale> | type AccountName = String |
| 02:51:52 | <mmorrow> | (which could manifest itself it different ways i guess, e.g. "Foo.Bar.Baz.Sales") |
| 02:51:54 | <Berengal> | Sounds like the perfect job for a trie... |
| 02:52:41 | <mmorrow> | exactly, then once you've built the trie, you can turn it into a Tree fairly easily |
| 02:52:48 | <sm> | ACTION is converting ["assets", "assets:bank", "assets:bank:checking", "expenses:food"] to a tree |
| 02:52:56 | <mmorrow> | perfect |
| 02:52:59 | <sm> | and it had been O(n^2) |
| 02:53:20 | <mmorrow> | bb in a minute |
| 02:54:09 | <sm> | and Cale gave me a non-n^2 tree builder which worked for him.. but doesn't have much effect in my app yet |
| 02:55:37 | <sm> | I'm also trying to learn how to efficiently profile and tune haskell. Part of my brain is saying "you wouldn't be spending this time if it was python" |
| 02:56:51 | <MyCatVerbs> | sm: you also wouldn't get anywhere near the same ceiling if it was Python, so meh. |
| 02:57:13 | <MyCatVerbs> | sm: anyways, I trust you are using ghc-core for the awkward tuning bits? |
| 02:57:26 | <Cale> | MyCatVerbs: Nothing at that level |
| 02:58:02 | <Cale> | ghc-core is useful when you're worried about how things are optimised... this is an asymptotic problem, most likely |
| 02:58:20 | <MyCatVerbs> | Oh? Oh, aye. Excuse my thinking in constant factors. ^^ |
| 02:58:43 | <Cale> | sm: Is that darcs repo current? |
| 02:59:18 | <sm> | no it isn't.. I'll make it so |
| 03:01:16 | <thoughtpolice> | ACTION hopes he can make it to hac phi... |
| 03:01:24 | <thoughtpolice> | thank goodness it's in july; I won't have class :) |
| 03:02:07 | <sm> | Cale: pushed the latest |
| 03:02:55 | <sm> | if you are profiling, I should make you a data file like the one I have here |
| 03:03:24 | <mgsloan> | has anyone thought about writing a tool to analyze large volumes of haskell code (spider for code on the internet), and generate a list of functions which abstract the most frequent replications? |
| 03:05:51 | <dmwit> | mgsloan: I know of at least one person who has thought about it. |
| 03:06:16 | <mgsloan> | and that's me! just kidding. it would be very interesting. |
| 03:06:25 | <dmwit> | Yeah, it would be! |
| 03:06:29 | <dmwit> | You should definitely do it. |
| 03:07:35 | <mgsloan> | Maybe this summer I'll give it a go :) interning at adobe might be enough coding for the summer though, hrmm |
| 03:08:29 | <myname> | any body uses xmobar's Mail plugin? |
| 03:08:49 | <dmwit> | myname: Ask on #xmonad, there's more likely to be people using xmobar there. |
| 03:09:00 | <idnar> | sm: if you think profiling and tuning python is easy, I'd love to know what your secret weapon is :P |
| 03:09:02 | <myname> | thanks |
| 03:09:08 | <mgsloan> | You would probably need some sort of canonical form, which minimizes the difference between re-expression of a similar concepts |
| 03:09:48 | <idnar> | sm: I actually think GHC's tools are a lot better in several areas |
| 03:11:15 | <dmwit> | > groupBy (/=) [1,2,3,2,1,2,3] |
| 03:11:17 | <lambdabot> | [[1,2,3,2],[1,2,3]] |
| 03:11:24 | <dmwit> | Oh, that is just too slick. |
| 03:11:31 | <dmwit> | I'm going to hate myself tomorrow for writing the code this way. |
| 03:11:58 | <idnar> | how the heck does that work? |
| 03:12:14 | <idnar> | @src groupBy |
| 03:12:14 | <lambdabot> | groupBy _ [] = [] |
| 03:12:15 | <lambdabot> | groupBy eq (x:xs) = (x:ys) : groupBy eq zs |
| 03:12:15 | <lambdabot> | where (ys,zs) = span (eq x) xs |
| 03:12:21 | <Gracenotes> | groups by the first element of the list |
| 03:12:35 | <Gracenotes> | into blocks beginning with that element |
| 03:12:53 | <idnar> | oh, groupBy isn't what I thought |
| 03:13:06 | <Cale> | sm: I have something for you to test. Not sure if it will improve performance, but it's something to try. |
| 03:13:10 | <dmwit> | > groupBy (/=) [] |
| 03:13:12 | <lambdabot> | [] |
| 03:13:17 | <dmwit> | ah, rats |
| 03:13:28 | <dmwit> | Oh well, I can just declare that nobody pass me []. |
| 03:13:49 | <sm> | Cale: great |
| 03:13:57 | <Cale> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5362#a5362 |
| 03:15:06 | <sm> | idnar: you may be right. That part of my brain is just saying that mutability would - in practice, for me writing this app - avoid all this in the first place. Bringing other costs with it down the road of course. |
| 03:15:32 | <idnar> | sm: I think it's all about trade-offs |
| 03:15:54 | <sm> | indeed. I'd like to understand those well |
| 03:15:58 | <idnar> | sm: not only trade-offs in the language itself, but also in what you're familiar with, and the "community knowledge" that exists |
| 03:16:10 | <sm> | agreed |
| 03:18:23 | <idnar> | I'm kinda optimisation-weary right now; I've spent the last week and a half optimising Python code :) |
| 03:18:34 | <sm> | Cale: total time = 4.98 secs (249 ticks @ 20 ms) |
| 03:18:34 | <sm> | total alloc = 1,803,104,924 bytes (excludes profiling overheads) |
| 03:18:43 | <idnar> | fortunately I've been targetting CPU time, not memory usage |
| 03:19:00 | <Cale> | Better? |
| 03:19:10 | <sm> | yes it seems a couple of secs faster |
| 03:19:40 | <Cale> | It's a lot of allocation, but it should all be immediate garbage. |
| 03:20:37 | <sm> | just for reference, the Competition (c++ ledger) does this in .4s |
| 03:21:21 | <sm> | I was using this quite happily, then some boor pointed this out on the list.. |
| 03:21:52 | <idnar> | heh |
| 03:22:08 | <Cale> | Well, you are using a lot of Strings... |
| 03:22:28 | <p_l> | sm: which c++ ledger? |
| 03:22:30 | <Cale> | It's also probably possible to do this tree construction more directly |
| 03:22:57 | <sm> | p_l: http://wiki.github.com/jwiegley/ledger |
| 03:23:15 | <Cale> | Seems a bit of a shame to switch back and forth between a Trie of the components and a Data.Tree... |
| 03:23:38 | <p_l> | sm: wasn't it obsoleted by the author? :) |
| 03:23:57 | <sm> | not at all.. 3.0 will be out when he gets back to it |
| 03:24:09 | <sm> | meanwhile I have been hacking on our righteous http://hledger.org |
| 03:24:09 | <p_l> | sm: Right, seems like the C++ version still gets some work |
| 03:25:32 | <sm> | Cale: maybe time I read up on trie and used it throughout then. I still wonder if any of this "advanced" optimisation is required.. if I would just not call these things 800k or 2 million times |
| 03:25:38 | <mmorrow> | sm: here's some Trie code that i use a bunch and a speed test (builds a Tree of 1000 random [String]'s by way of an intermediate Trie) that's pretty speedy http://moonpatio.com/repos/trie-test/ |
| 03:25:52 | <Cale> | sm: Right, that's sort of what I was asking about before. |
| 03:25:56 | <dibblego> | is there a safe (!!)? (to return Maybe)? |
| 03:26:42 | <Cale> | sm: Actually it would be interesting to see the new profile |
| 03:26:44 | <mmorrow> | (i used this trie-code when i was doing that account grouping thing too, and it worked out well (thousands of hierarchical accounts from a db and treeify -> webpage (w/ sparklines!)) |
| 03:27:27 | <Cale> | It's not exactly a conventional Trie which I was using either, but one where the account name path components are the alphabet :) |
| 03:27:49 | <mmorrow> | exactly |
| 03:28:10 | <mmorrow> | (which is a Trie in my book) |
| 03:28:12 | <Cale> | Which I think models the directory tree structure that it's going for best anyway |
| 03:28:14 | <sm> | brb |
| 03:28:31 | <Cale> | So it might be worthwhile to make other code in the program use that type. |
| 03:28:48 | <mmorrow> | my trie type is: |
| 03:28:54 | <mmorrow> | newtype Trie m k a = Trie (Maybe a, m (SubKey k) (Trie m k a)) |
| 03:28:58 | <Cale> | newtype Tree' a = T (Map a (Tree' a)) |
| 03:29:00 | <mmorrow> | type family SubKey k |
| 03:29:00 | <mmorrow> | type instance SubKey [k] = |
| 03:29:04 | <mmorrow> | k |
| 03:29:19 | <mmorrow> | (and i'm using Data.Map for the m) |
| 03:29:34 | <Cale> | cool |
| 03:29:58 | <mmorrow> | i used okasaki's trie chapter from purely funcitonal datastructures |
| 03:29:59 | <mmorrow> | http://moonpatio.com/repos/trie-test/Trie.hs |
| 03:30:30 | <mmorrow> | (i had to use a function on haskell records of functions to model his sml functor though) |
| 03:30:42 | <mmorrow> | trie :: M m k (Trie m [k] a) -> M (Trie m) [k] a |
| 03:31:06 | <mmorrow> | (is the "sml functor") |
| 03:32:02 | <sm> | Cale: latest profile with your change: http://joyful.com/repos/hledger/profs/200905282017.prof |
| 03:32:24 | <Cale> | Oh, interesting. |
| 03:32:35 | <Cale> | So now it's *really* ledgerAccount which we need to attack |
| 03:33:01 | <Cale> | Well, or the need to call that in the first place |
| 03:33:56 | <mmorrow> | what does ledgerAccount do? |
| 03:34:05 | <Cale> | It's just a map lookup, I think. |
| 03:34:16 | <Cale> | The real problem is that it's being called 800,000 times |
| 03:34:34 | <Cale> | (when the map is nowhere near that large, even) |
| 03:35:13 | <mmorrow> | what's the Map of? |
| 03:35:13 | <Cale> | hmmm |
| 03:35:40 | <mmorrow> | (and what's the Map's key type?) |
| 03:35:41 | <Cale> | Damnit I hate firefox's copy/paste shenanigans |
| 03:35:52 | <Cale> | > 821161 / 2457 |
| 03:35:54 | <lambdabot> | 334.2128612128612 |
| 03:35:56 | <Cale> | hmm |
| 03:36:47 | <Cale> | mmorrow: String |
| 03:37:01 | <Cale> | ledgerAccount :: Ledger -> AccountName -> Account |
| 03:37:01 | <Cale> | ledgerAccount l a = (accountmap l) ! a |
| 03:37:23 | <mmorrow> | ooh, String will kill |
| 03:37:48 | <Cale> | Yeah, but I somehow don't think that's the main problem. |
| 03:37:55 | <mmorrow> | personally i'd map strings to Ints somehow, and use IntMap |
| 03:38:20 | <Cale> | I don't care for IntMap very much somehow. It's always seemed like an ugly hack to me. |
| 03:38:31 | <mmorrow> | i dunno, Int compare is like a single machine instr, whereas String compare is .. |
| 03:38:40 | <Cale> | (but I'm morally opposed to Int in the first place ;) |
| 03:38:50 | <mmorrow> | Cale: i never cared for it either, until i saw how cool of a structure it is |
| 03:39:00 | <mmorrow> | for instance, it never needs rebalancing |
| 03:39:06 | <mmorrow> | and union is best-case O(1) |
| 03:39:18 | <Cale> | String comparisons are lexicographical though, so, most of the time you don't compare the whole thing |
| 03:40:06 | <Cale> | sm: Is the average number of accounts per ledger around 300? |
| 03:40:13 | <Cale> | That seems high... |
| 03:40:17 | <mmorrow> | (and IntMap nodes have the Int key unboxed into them, whereas Map nodes have a ptr to the key) |
| 03:41:12 | <Cale> | mmorrow: Yeah, but this is all stuff which should be hidden behind the Data.Map library. I shouldn't have to import a separate module and use a different datatype. |
| 03:41:39 | <Cale> | Maps which happen to have Int keys should just be fast :) |
| 03:41:53 | <mmorrow> | IntMap could just as well be IntegerMap, the only thing it needs is the ability to do bitwise ops on the key type |
| 03:42:02 | <mmorrow> | (it's a BitTrie..) |
| 03:42:24 | <sm> | Cale: I think it would lower for most.. |
| 03:42:25 | <mmorrow> | Map and IntMap are totally diff structures |
| 03:42:43 | <Cale> | mmorrow: Right, getting the polymorphic stuff to work is hard. |
| 03:43:12 | <Cale> | sm: |
| 03:43:12 | <mmorrow> | yeah, and patricia trees don't even work if you can't do bitwise stuff on the key |
| 03:43:15 | <Cale> | > 821161 / 2457 |
| 03:43:17 | <lambdabot> | 334.2128612128612 |
| 03:44:13 | <fracture> | anyone know if there's a way to :step in ghci that doesn't doesn't step into stuff it needs to compute to get the current expression? |
| 03:44:23 | <fracture> | or like a step out |
| 03:44:26 | <fracture> | couldn't find it in the manual |
| 03:44:43 | <Cale> | I think the stepping commands are somewhat limited... |
| 03:44:50 | <Cale> | fracture: what are you trying to analyse? |
| 03:45:12 | <fracture> | well, I have this search thing that I've figured out is going into an infinite loop |
| 03:45:21 | <fracture> | and I'm trying to understand the conditions that cause it to do so |
| 03:45:36 | <fracture> | (at least I think it's going infinite) |
| 03:45:49 | <Cale> | Maybe start by plonking a Debug.Trace.trace into it which prints the parameters that it's called with each time. |
| 03:46:10 | <Cale> | that way you can figure out how it's being called at least |
| 03:46:26 | <fracture> | the data structure is somewhat large... it'd be nicer to be able to inspect it in the debugger |
| 03:46:50 | <Cale> | Do you know which function it is? |
| 03:46:52 | <fracture> | how do you put a trace in, by the way? const function? |
| 03:46:54 | <fracture> | yeah |
| 03:47:22 | <Cale> | What's it's type? |
| 03:47:28 | <fracture> | like .. const foo (trace "asd") ? |
| 03:47:36 | <fracture> | solve :: Board -> Int -> Maybe Board |
| 03:47:47 | <fracture> | board is data Board = Board (Array (Int,Int) Int) deriving Show |
| 03:47:51 | <Cale> | okay |
| 03:47:57 | <Cale> | add a case: |
| 03:48:38 | <Cale> | solve b i | trace (concat ["solve: ", show b, " ", show i]) False = undefined |
| 03:48:42 | <Cale> | at the top |
| 03:49:00 | <fracture> | ok |
| 03:49:02 | <Cale> | The guard will always fail, but its evaluation will print that message |
| 03:49:20 | <fracture> | ah nice |
| 03:49:38 | <Cale> | Then you can comment out that line to stop tracing. |
| 03:51:12 | <mmorrow> | ooh, handay |
| 03:51:38 | <fracture> | cool; this should work to debug this (thanks) |
| 03:51:40 | <Cale> | In general, trace str x is a value which is the same as x, but when x gets pattern matched against, the string str is printed on stderr |
| 03:51:43 | <bos> | is anyone planning on going to hac φ? |
| 03:51:55 | <fracture> | got ya |
| 03:51:55 | <mmorrow> | bos: i'd like to |
| 03:52:01 | <bos> | ACTION is thinking about it |
| 03:52:18 | <mmorrow> | nice |
| 03:52:38 | <mauke> | oleg++ |
| 03:53:16 | <mauke> | hmm, this may have the unintended side effect of strictifying solve |
| 03:53:23 | <mauke> | deep strict |
| 03:53:25 | <Cale> | Yes, it will. |
| 03:53:34 | <Cale> | I've had that be a problem before too ;) |
| 03:53:40 | <fracture> | hmm... now I'm not so sure it's in an infinite loop :) |
| 03:53:43 | <fracture> | guess I gotta think about this more |
| 03:53:47 | <ivanm> | mauke: what has oleg done this time? |
| 03:54:28 | <mauke> | AFAIK he invented the | ... False = undefined trick; at least that's where I learned about it |
| 03:54:42 | <Cale> | I stole it from the original definition of undefined |
| 03:54:50 | <Cale> | Which was |
| 03:54:53 | <mmorrow> | mauke: i heard that if you say oleg's name 3 times into a mirror in the darc he'll appear out of nowhere and delimit your continuation |
| 03:54:57 | <Cale> | undefined | False = undefined |
| 03:55:20 | <mauke> | redundant |
| 03:55:34 | <Cale> | It's undefined, but not an infinite loop. |
| 03:55:38 | <mmorrow> | i thought undefined was |
| 03:55:42 | <mmorrow> | undefined = undefined |
| 03:55:55 | <mauke> | http://okmij.org/ftp/Haskell/#making-function-strict |
| 03:55:57 | <Cale> | This way you get a pattern match failure. |
| 03:56:18 | <Cale> | Yeah, it's good for that sort of thing too. |
| 03:56:31 | <mmorrow> | i've heard people say they like the "undefined = undefined" way more because it was more "instructive" :) |
| 03:56:38 | <Cale> | Though not usually necessary now that we have bang patterns. |
| 03:56:55 | <mauke> | __ = __ -- to quote oleg again |
| 03:57:12 | <mmorrow> | um |
| 03:57:12 | <ivanm> | mmorrow: though doesn't ghc define it as an error? |
| 03:57:18 | <mmorrow> | ivanm: yes |
| 03:57:37 | <Berengal> | @src undefined |
| 03:57:37 | <lambdabot> | undefined = error "Prelude.undefined" |
| 03:57:38 | <mmorrow> | oh, no |
| 03:57:40 | <mmorrow> | err,m yeah |
| 03:57:48 | <mmorrow> | which itself is UserError or something |
| 03:57:50 | <hatds> | which is, of course, more useful :) |
| 03:57:53 | <ivanm> | so that strictness tricks evaluates everything, but because the actual value is False, it never returns undefined? |
| 03:58:12 | <fracture> | hmm.. so in an imperative language, I could add some of these Boards to a map and look them up to see if I've called the function with exactly that before |
| 03:58:15 | <fracture> | any similar trick in this? |
| 03:58:18 | <Berengal> | ivanm: Well, as long as none of the arguments being forced are undefined |
| 03:58:23 | <fracture> | or should I just pipe stderr to some file and use perl :) (hah) |
| 03:58:52 | <fracture> | (they are too large to really verify by hand) |
| 03:59:29 | <fracture> | seems like that concept doesn't really carry over here... |
| 03:59:37 | <mauke> | memoizing? |
| 03:59:44 | <dmwit> | http://article.gmane.org/gmane.comp.lang.haskell.cafe/7737 |
| 03:59:46 | <mmorrow> | ivanm: (undefined used to be undefined = undefined from what i understand..) |
| 03:59:48 | <dmwit> | (@fracture) |
| 03:59:56 | <ivanm> | mmorrow: *nod* |
| 04:00:03 | <ivanm> | except then it would never return anything? |
| 04:00:04 | <fracture> | well, except in this situation memoizing to aid debugging (hah) |
| 04:00:11 | <mmorrow> | ivanm: heh, exactly |
| 04:00:15 | <ivanm> | and would cause your program to loop rather than return an error? |
| 04:00:20 | <mmorrow> | yup |
| 04:00:21 | <ivanm> | s/return/throw/ |
| 04:00:26 | <mmorrow> | "instructive" ;) |
| 04:00:34 | <fracture> | yeah |
| 04:00:35 | <mmorrow> | (for some value thereof) |
| 04:02:32 | <Berengal> | I used to find it more instructive that errors and infinite loops were the "same" |
| 04:06:09 | <mmorrow> | i'd find it amusing maybe the first time, then just get pissed :) |
| 04:06:24 | <mmorrow> | (if undefined = undefined) |
| 04:11:11 | <mauke> | <<loop>> |
| 04:11:37 | <mauke> | you know, I have this esoteric language with no errors |
| 04:11:47 | <mauke> | any sequence of characters is a valid program |
| 04:11:58 | <ray> | you mean godel numbering? |
| 04:12:13 | <mauke> | nothing as fancy as that |
| 04:12:34 | <mauke> | any runtime problems (such as a jump to a non-existing label) are "reported" by falling into an infinite loop |
| 04:12:49 | <ray> | that's not so esoteric |
| 04:13:08 | <mauke> | well, it's some kind of bottom, but I didn't know that when I "designed" it |
| 04:13:38 | <ray> | i should say, it doesn't sound too esoteric for #haskell |
| 04:13:44 | <mauke> | it used to do that simply because I did a linear search over all instruction, wrapping back to the beginning |
| 04:13:53 | <mauke> | +s |
| 04:14:13 | <mauke> | (oh, and it didn't even read the program into memory, so it was a fgets() loop + rewind()) |
| 04:15:07 | <ray> | sounds like the paradigm of the future |
| 04:16:04 | <mauke> | the new (completely rewritten) interpreter does create an in-memory representation of the program and detects some infinite loops, optimizing them to sleep() calls |
| 04:16:44 | <whoppix> | awesome. |
| 04:20:18 | <sm> | ack.. gf phone call + a plumbing emergency |
| 04:20:28 | <ray> | @quote infinitely |
| 04:20:28 | <lambdabot> | Berengal says: [On infinitely fast computers] The OS probably has a failsafe built in: If a program is running it's in an infinite loop and needs to be killed... |
| 04:21:21 | <sm> | don't these people understand I am *debugging* |
| 04:23:43 | <inimino> | mauke: interesting idea, I was thinking about total parsing, where every string is a valid parse |
| 04:24:15 | <inimino> | mauke: I guess you could write a language to make APL look verbose |
| 04:24:46 | <mauke> | http://home.cs.tum.edu/~mai/ploki/ploki-0.6.4/examples/calc.pk |
| 04:25:46 | <mmorrow> | mauke: yeah true, i guess that'd just die with a <<loop>> |
| 04:26:16 | <inimino> | heh |
| 04:26:37 | <mriou> | I'm looking for pointers to implement a binary tree efficiently (mostly, not recreate the whole tree to change one leaf) |
| 04:27:21 | <mriou> | is there anything I should look at? |
| 04:27:30 | <mauke> | data Tree a = Leaf | Node a (Tree a) (Tree a) |
| 04:27:39 | <mmorrow> | mriou: if you just replace a node, the whole tree won't be copied |
| 04:28:07 | <sjanssen> | mriou: I recommend Okasaki's data structures book if you can get it from your local library |
| 04:28:14 | <mmorrow> | mriou: since haskell uses graph reduction that falls out for free |
| 04:28:40 | <mriou> | mmorrow that's sweet, didn't know that :) |
| 04:29:30 | <mriou> | mauke: the only difference is that my tree has no node value |
| 04:29:35 | <mriou> | just leaf values |
| 04:30:25 | <mriou> | thanks for the pointer sjanssen |
| 04:31:18 | <hatds> | data CallStack a = Return a | Push (Env -> CallStack a) with: (>>=) (Push g) f = Push $ \e -> g e >>= f |
| 04:31:31 | <hatds> | heh, what do we think? :) |
| 04:34:03 | <mmorrow> | hatds: how will you unwind though? |
| 04:34:30 | <hatds> | hm |
| 04:34:30 | <mmorrow> | (and recover the Envs you pass in to the Push functions) |
| 04:34:36 | <Cale> | Hmm, is that a monad? |
| 04:34:40 | <hatds> | I'm assuming Env isn't changed |
| 04:34:43 | <hatds> | yea, I think so |
| 04:35:44 | <hatds> | I think one can write a function CallStack a -> a, yea? |
| 04:36:06 | <Cale> | Env -> CallStack a -> a, certainly |
| 04:36:57 | <hatds> | I wonder if it is efficient |
| 04:37:10 | <mmorrow> | i've used (data Cxt a b = Top a | Loc b (b -> Cxt a b)) before |
| 04:37:36 | <mmorrow> | it seems like something is inside-out about that CallStack though (i can't quite put my finger on it though) |
| 04:38:39 | <mmorrow> | actually, Cxt a = Top a | Loc a (a -> Cxt a) is easier to deal with |
| 04:39:04 | <mmorrow> | (and you'd need a (into :: a -> Cxt a)) |
| 04:39:36 | <hatds> | into = return for the Cxt monad? |
| 04:39:42 | <bitfish> | hi, i'm always getting this error while trying to `run` the following file: http://paste.pocoo.org/show/phVbwbCUssN1GIKItI3x/ |
| 04:39:58 | <mmorrow> | hmm, it's not quite return.. it'd be dependent on your particular 'a' |
| 04:40:07 | <bitfish> | and the error: foo.hs:2:0: parse error (possibly incorrect indentation) |
| 04:40:10 | <mauke> | bitfish: yeah, you can't do that |
| 04:40:14 | <mmorrow> | and there'd probably be more than one into |
| 04:40:15 | <bitfish> | any ideas what i'm doing wrong? |
| 04:40:23 | <bitfish> | mauke: what do you mean? |
| 04:40:26 | <Cale> | bitfish: .hs files should consist of declarations |
| 04:40:27 | <mmorrow> | data T a = Tip a | T (T a) (T a) |
| 04:40:36 | <mauke> | bitfish: you can't just put some statements in a .hs file |
| 04:40:46 | <Cale> | bitfish: write something like |
| 04:40:47 | <bitfish> | mauke: i can't? |
| 04:40:59 | <Cale> | hw = "Hello, World!" |
| 04:41:04 | <Cale> | main = print hw |
| 04:41:17 | <bitfish> | okay |
| 04:41:18 | <Cale> | (or putStrLn instead of print) |
| 04:41:21 | <mmorrow> | left (Loc (T l r) k) = Loc l (\l -> k (T l r)) |
| 04:41:25 | <mmorrow> | right = ... |
| 04:41:39 | <mauke> | main = do { let hw = "Hello, world!\n"; putStr hw; } |
| 04:41:41 | <mauke> | :-) |
| 04:41:47 | <hatds> | what's the monad instance for Cxt? |
| 04:41:56 | <mmorrow> | err, i messed up the description of into.. |
| 04:42:03 | <mmorrow> | hatds: there isn't one |
| 04:42:10 | <mmorrow> | (maybe there is, not sure) |
| 04:42:12 | <hatds> | that's no fun then |
| 04:42:18 | <mmorrow> | heh |
| 04:42:20 | <wahjava> | hi |
| 04:42:23 | <hatds> | I wanted something where return was like the C keyword |
| 04:42:39 | <mmorrow> | which one? return? |
| 04:42:43 | <ray> | sounds hard |
| 04:42:48 | <bitfish> | mauke: heh, well, i'm a bloody newb to haskell, not to programming at all. its fun to learn a new language ;) |
| 04:42:52 | <hatds> | here's the whole thing |
| 04:42:57 | <hatds> | data CallStack a = Return a | Push (Env -> CallStack a) |
| 04:42:59 | <hatds> | instance Monad CallStack |
| 04:43:01 | <hatds> | return a = Return a |
| 04:43:02 | <hatds> | (>>=) (Return a) f = f a |
| 04:43:04 | <hatds> | (>>=) (Push g) f = Push $ \e -> g e >>= f |
| 04:43:20 | <Cale> | Note that (Push g) >>= f = Push (g >=> f) |
| 04:43:31 | <wahjava> | is there any 'trim' function in haskell library ? 'trim' is supposed to remove continuous occurence of a specific character at the start and end of the string. |
| 04:43:49 | <hatds> | nice, Cale |
| 04:43:49 | <mauke> | dropWhile |
| 04:44:17 | <SamB> | why does the kleisli arrow look like a fish ? |
| 04:44:24 | <Cale> | bitfish: The basic idea is that declarations go in a file, you load that in ghci and you can type expressions to evaluate them. |
| 04:44:38 | <mmorrow> | so you're really using Return as a way to _call_ a function, and Push as a way to (in a sense) return |
| 04:44:50 | <bitfish> | Cale: that sounds rather irritating |
| 04:44:53 | <Cale> | bitfish: In a compiled program, you define an IO action value which says what to do when the program runs. |
| 04:44:59 | <mmorrow> | (Return a >>= f to call a function) |
| 04:45:04 | <hatds> | bitfish: think of a .hs structured more like a C file rather than a list of statements for ghci |
| 04:45:14 | <Cale> | bitfish: It's not bad. Just keep two terminal windows open, one with your editor, and one with ghci |
| 04:45:28 | <bitfish> | okay |
| 04:45:29 | <Cale> | bitfish: When you edit the file, typing :r in ghci will reload it. |
| 04:45:45 | <Cale> | and you can continue to test things |
| 04:45:48 | <mmorrow> | hatds: i dunno, do you have an example of CallStack being used? |
| 04:46:16 | <hatds> | this is potentially part of my mini-GUI library design |
| 04:46:19 | <SamB> | or you could use a text editor that actually runs natively under your window system, like emacs ;-) |
| 04:46:24 | <rzezeski> | can someone look at this paste and tell me if I'm tracing functions correctly... http://paste.lisp.org/display/81003 |
| 04:46:38 | <hatds> | and Env = Event |
| 04:46:48 | <mmorrow> | hatds: or maybe i should say, what is CallStack's purpose? |
| 04:46:54 | <mmorrow> | hmm |
| 04:46:54 | <wahjava> | mauke, > dropWhile Data.Char.isSpace " wahjava " |
| 04:47:02 | <bitfish> | SamB: i always use the KDE Kate editor (under GNOME) to edit files |
| 04:47:11 | <Cale> | rzezeski: I would if paste.lisp.org resolved for me... |
| 04:47:14 | <bitfish> | SamB: i'll think about that :P |
| 04:47:16 | <Cale> | oh, there we go |
| 04:47:21 | <wahjava> | mauke, that only removes spaces at beginning, what about removal of spaces at the end ? |
| 04:47:32 | <rzezeski> | Cale: thx for looking Cale |
| 04:47:33 | <hatds> | mmorrow: a GUI is a lot like f : Event -> IO (), but maybe I have two such functions f1 and f2 and I want to "switch over" to f2 after this event |
| 04:47:36 | <mauke> | wahjava: reverse . dropWhile _ . reverse |
| 04:47:39 | <SamB> | bitfish: that obviously also runs natively under your window system |
| 04:47:42 | <SamB> | ;-) |
| 04:47:47 | <bitfish> | i know, heh |
| 04:47:48 | <wahjava> | mauke, okay. thanks :) |
| 04:48:24 | <Cale> | rzezeski: You're a little off, it should be foldl step (step 0 '9') "85" |
| 04:49:02 | <Cale> | rzezeski: Also, it's the outermost step which evaluates first |
| 04:49:16 | <sm> | argh.. what function converts 'a' and 'b' to "ab" ? |
| 04:49:26 | <mauke> | \a b -> [a, b] |
| 04:49:42 | <sm> | phew, thank you |
| 04:50:11 | <rzezeski> | Cale: when you say outtermost step, do you mean after the foldl is done doing its thing? |
| 04:50:19 | <hatds> | I guess 'return ()' is like poping the stack |
| 04:50:50 | <Cale> | yeah |
| 04:50:57 | <Cale> | the outermost call to 'step' |
| 04:51:07 | <rzezeski> | Cale: I think you can annotate my paste, if you want to be a super nice guy :) |
| 04:51:41 | <Cale> | rzezeski: I'm writing out a trace already :) |
| 04:51:52 | <rzezeski> | Cale: thx, you tha man! |
| 04:53:14 | <rzezeski> | Cale: BTW, the reason I did the innermost first is because I thought parens took precedence over a function precedence...I'm sure your trace will clear it up for me |
| 04:53:38 | <mauke> | precedence is not evaluation order |
| 04:54:29 | <rzezeski> | mauke: so what is evaluate first in this contrived example: fn1 (fn2 somarg2) somearg1 |
| 04:54:51 | <mauke> | fn1 |
| 04:55:00 | <Cale> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5366#a5366 |
| 04:55:10 | <rzezeski> | ahh, and that's where I have gone astray it seems |
| 04:55:27 | <Cale> | oops, I doubled a line there |
| 04:56:17 | <Cale> | I'll show how it goes with foldl' |
| 04:57:20 | <rzezeski> | Cale: I see what you mean now, I think I have to re-read the RWH section about evaluation, apparently I still have it wrong |
| 04:57:49 | <copumpkin> | how long until someone on-ups bos' pidigits entry? |
| 04:58:34 | <dmwit> | In Haskell or at all? |
| 04:58:36 | <rzezeski> | BTW, I like hpaste, it doesn't blow up like paste.lisp when I tell it to colorize for Haskell |
| 04:58:51 | <bos> | copumpkin: i'd be thrilled if someone did |
| 04:59:04 | <copumpkin> | bos: I meant in c :( |
| 04:59:09 | <mauke> | http://www.spoj.pl/ranks/PIVAL/ ? |
| 04:59:10 | <sm> | uniquenames = map (λa→[a]) "abcdefghijklmnopqrstuvwxyz" ++ (zipWith (++) uniquenames uniquenames) |
| 04:59:28 | <copumpkin> | I wonder how parallelizable it is... it feels pretty sequential to me |
| 04:59:34 | <bos> | copumpkin: i think that's probably not possible. |
| 04:59:41 | <sm> | would someone have a nicer implementation ? I'd like eg 1000 or 10000 readable randomish similarish-length unique strings |
| 05:00:49 | <mauke> | :t showIntAtBase |
| 05:00:50 | <lambdabot> | forall a. (Integral a) => a -> (Int -> Char) -> a -> String -> String |
| 05:01:00 | <hatds> | unique strings or just random-y? |
| 05:01:16 | <mauke> | > map (\n -> showIntAtBase 26 (['a' .. 'z'] !!) n "") [0 ..] |
| 05:01:18 | <lambdabot> | ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s... |
| 05:01:20 | <dmwit> | uniquenames = [1..] >>= \n -> replicateM n ['a'..'z'] >>= id |
| 05:01:22 | <sm> | hatds: unique.. they don't have to be random |
| 05:01:34 | <mauke> | >>= id is join |
| 05:01:38 | <dmwit> | > do { n <- [1..]; s <- replicateM n ['a'..'z']; s } |
| 05:01:40 | <lambdabot> | "abcdefghijklmnopqrstuvwxyzaaabacadaeafagahaiajakalamanaoapaqarasatauavawax... |
| 05:01:57 | <dmwit> | mauke: I know. But then I'd have to prefix that, and it breaks the beauty of it. Plus it's wrong. |
| 05:02:00 | <hatds> | sm: fromEnum :: Int -> Char, now just get random nums? |
| 05:02:01 | <dmwit> | > do { n <- [1..]; s <- replicateM n ['a'..'z'] } |
| 05:02:04 | <lambdabot> | <no location info>: |
| 05:02:04 | <lambdabot> | The last statement in a 'do' construct must be an ... |
| 05:02:04 | <dmwit> | bah |
| 05:02:08 | <dmwit> | > do { n <- [1..]; replicateM n ['a'..'z'] } |
| 05:02:10 | <lambdabot> | ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s... |
| 05:02:16 | <Cale> | rzezeski: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5366#a5367 |
| 05:02:33 | <dmwit> | :t [1..] >>= flip replicateM ['a'..'z'] |
| 05:02:36 | <lambdabot> | [[Char]] |
| 05:02:43 | <copumpkin> | bos: I'm curious how limiting gmp's function boundaries are for this (i.e., if we had a pure haskell multiprecision lib almost as fast as GMP and good ways of fusing adjacent operations, whether we could do better) |
| 05:03:16 | <Cale> | rzezeski: While it may look like more steps, it's mostly because I included steps for trivial things which are not really steps, like substituting let-bound things into expressions. |
| 05:03:44 | <Cale> | (and eliminating seq when the variable is evaluated) |
| 05:03:46 | <jfredett_> | do there exist Object-relational model database libraries for haskell? HDBC and HaskellDB both appear to be SQL executors. |
| 05:04:10 | <bos> | copumpkin: i don't know for sure, but i'm dubious. |
| 05:04:20 | <jfredett_> | or will I need to build one? :) |
| 05:04:39 | <Cale> | jfredett_: What would the interface look like? |
| 05:05:06 | <sm> | jfredett_: I think you will need to build it |
| 05:05:54 | <jfredett_> | Cale: I don't know- I suppose one could hijack Data.Map and just have the fields be a autogenerated datatype based on the table info... |
| 05:06:03 | <Cale> | Has anyone here tried HaskellDB lately? |
| 05:06:11 | <Cale> | Is it still cool? :) |
| 05:06:49 | <jfredett_> | Reason being, I'm trying to write a binding to an API/Database for EVE online, and I wanted to provide a consistent, mostly pure interface to the database (which houses worldmap and item info). |
| 05:07:08 | <rzezeski> | Cale: Thx, you've been a big help, again! |
| 05:07:16 | <Cale> | rzezeski: No problem :) |
| 05:07:17 | <jfredett_> | and I thought about building a big record, but it's a _big_ record for even one or two tables, and it's somewhat unwieldy looking |
| 05:08:23 | <Cale> | jfredett: You might want to look at the way that HaskellDB does things for inspiration |
| 05:08:39 | <Cale> | jfredett: It takes a more functional approach than an object oriented one though |
| 05:08:45 | <jfredett> | interesting |
| 05:09:00 | <jfredett> | I'll have to take a peek |
| 05:10:32 | <Cale> | I wonder if there's a good tutorial lying around... things have gotten more elaborate than last time I looked at it :) |
| 05:10:36 | <jfredett> | see- ideally, I'd like to take the table definition and have it roll some datatype defs and accessor-y database quereys. |
| 05:10:50 | <jfredett> | HDBC is lovely, very no nonsense. |
| 05:11:19 | <jfredett> | not super featureful, but nice for hacking. |
| 05:11:45 | <Cale> | HaskellDB's approach is that it provides you operators for writing queries such that the type of the result can be inferred. |
| 05:12:08 | <jfredett> | featureful in the sense of doing lots of fancy things, as opposed to actual useful properties, of which there are many. |
| 05:13:18 | <jfredett> | Cale: see, thats what I would want- a powerfully-typed database. I'm not well-versed in database-fu, but it seems that stronger type information could be useful in databases... |
| 05:13:48 | <Cale> | http://www.cs.chalmers.se/~bringert/publ/haskelldb/haskelldb-db-2005.pdf |
| 05:13:56 | <Cale> | Some intro slides :) |
| 05:14:02 | <jfredett> | excellent |
| 05:14:20 | <ivanm> | Cale: but is there some conc slides as well? :p |
| 05:14:23 | <jfredett> | ACTION sends to his kindle |
| 05:14:31 | <jfredett> | huzzah. |
| 05:16:50 | <Cale> | jfredett: HaskellDB is less of an Object Relational Mapper and more of a Relation Relational Mapper :) |
| 05:17:29 | <jfredett> | hehe |
| 05:17:30 | <Cale> | (That is, it gives you operations for directly manipulating the relations expressed in the database, and constructing new ones (which correspond to queries) |
| 05:17:42 | <Cale> | ) |
| 05:17:44 | <Cale> | hehe |
| 05:17:47 | <ivanm> | jfredett: what, reading it on your computer not good enough for you? |
| 05:17:47 | <ivanm> | ;-) |
| 05:18:01 | <jfredett> | ivanm: well, I'm not on my computer 24/7 |
| 05:18:17 | <jfredett> | Cale: I definitely like the static checking of queries. |
| 05:18:18 | <ivanm> | but you're on your kindle 24/7? |
| 05:18:20 | <ivanm> | :p |
| 05:18:44 | <jfredett> | ivanm: well, the set of times I'm on my computer union the set of times I have my kindle available = 24/7 |
| 05:18:51 | <ivanm> | heh |
| 05:18:57 | <ray> | `union` |
| 05:19:04 | <ivanm> | though my initial point was because I figured you'd just read it _now_... |
| 05:19:22 | <jfredett> | ivanm: I'll scan it, but it'll be nice to have on my kindle as well |
| 05:19:35 | <ivanm> | ACTION ponders ways in which a kindle can not be functioning whilst jfredett isn't on his computer... |
| 05:19:42 | <ivanm> | batteries, etc. |
| 05:19:49 | <ivanm> | thereby not making the union == 24/7 :p |
| 05:19:59 | <jfredett> | I tag it, it gets sorted with all the other haskell stuff I have on there |
| 05:20:11 | <Nafai> | I think I'd like a kindle |
| 05:20:54 | <ivanm> | ACTION thinks he'd like the money for a kindle, and then spend it on something more worth-while |
| 05:21:04 | <jfredett> | Nafai: wait for the new one thats coming out soon, it's gonna have a better pdf reader |
| 05:21:08 | <jfredett> | it might even remember math |
| 05:21:14 | <jfredett> | err- render * |
| 05:21:17 | <ivanm> | heh |
| 05:21:21 | <jfredett> | too many conversations.... :/ |
| 05:21:35 | <Gracenotes> | I can remember math. sort of. |
| 05:21:42 | <ivanm> | I've pondered getting an XO for a while just because unlike other netbooks, you can use it as an ebook reader |
| 05:21:46 | <Cale> | Odd... the documentation for 'divide' is "Not in SQL92." |
| 05:22:07 | <Cale> | http://hackage.haskell.org/packages/archive/haskelldb/0.12/doc/html/Database-HaskellDB.html#v%3Adivide |
| 05:22:14 | <ivanm> | Cale: as in the official documentation? or the hDB documentation? |
| 05:22:17 | <ivanm> | ahhh, the latter |
| 05:22:25 | <p_l> | ACTION was thinking of gettin iLliad or similar, as they are simply PDA's with ePaper display :D |
| 05:22:41 | <ivanm> | p_l: never heard of iLliad |
| 05:22:52 | <jfredett> | Cale: I imagine that a kind of Object-Functional Relational Model could be concieved -- purity + ORM could make things very interesting. |
| 05:23:03 | <ivanm> | what's the significance of the capital for the second letter? to iMitate aPple? :p |
| 05:23:12 | <jfredett> | that and a strongly typed database could be very cool. |
| 05:23:45 | <Cale> | Hey, this lecture was apparently given by nibro... he's been around lately hasn't he? |
| 05:24:09 | <p_l> | ivanm: I don't know. |
| 05:24:10 | <ivanm> | @seen nibro |
| 05:24:10 | <lambdabot> | I saw nibro leaving #haskell 5h 49m 36s ago, and . |
| 05:24:20 | <ivanm> | Cale: he was around... |
| 05:24:28 | <ivanm> | s/was/_was_/ ;-) |
| 05:25:02 | <jfredett> | partially though, I'm just afraid I'm going to fall down the, "This is such an awesome idea, I should totally do this project too" rabbit hole, and pop out the other side with 1500 projects all stealing my time. :/ |
| 05:25:48 | <Cale> | It's too bad that we don't have a proper record system in Haskell. If we did, HaskellDB could be a good deal prettier. |
| 05:25:52 | <jfredett> | Thats the problem with haskell, it makes too many awesome ideas possible, so I get stuck with too many projects... :/ |
| 05:25:56 | <jfredett> | Cale: I agree. |
| 05:26:13 | <Cale> | Currently it has to cheat and use typeclass trickery to simulate proper records |
| 05:26:35 | <jfredett> | then again, I would have never had this question (or set thereof) if it did, so perhaps it's a good thing. |
| 05:26:44 | <jfredett> | got me thinking about interesting database stuff. |
| 05:27:25 | <ivanm> | Cale: what would you call a "proper record system"? |
| 05:27:58 | <ivanm> | the only real problem I have with the current one is that it's annoying doing foo {bar = succ (bar foo)} |
| 05:27:59 | <ivanm> | :s |
| 05:28:24 | <jfredett> | ivanm: dunno what Cale would say, but some kind of namespacing so that I could have data Foo = Foo {bar :: Int} and data Fuz = Fuz {bar :: String} |
| 05:28:31 | <Cale> | Well, the existing record syntax is a syntax for algebraic types which is different than what I'm thinking of |
| 05:28:33 | <jfredett> | without having a type error... |
| 05:28:53 | <ivanm> | jfredett: well, that can be argued both ways, since bar :: Foo -> Int and bar :: Fuz -> String |
| 05:29:29 | <Cale> | What I'm thinking of is extensible records with named/typed fields that are part of the record type, along with row polymorphism, and various operations on row types |
| 05:29:44 | <ivanm> | Cale: example? |
| 05:29:52 | <ivanm> | (so I know wtf you mean :p ) |
| 05:30:44 | <Cale> | So you could have a function... raise :: Integer -> { 'salary :: Integer | row } -> { 'salary :: Integer | row } |
| 05:31:03 | <jfredett> | ... wuuuuhhh? |
| 05:31:04 | <Cale> | Which would operate on any record type having a 'salary field. |
| 05:31:09 | <jfredett> | ooh |
| 05:31:10 | <Cale> | (of type integer) |
| 05:31:11 | <jfredett> | interesting. |
| 05:31:30 | <Cale> | Regardless of what other fields were in there. |
| 05:31:54 | <ivanm> | Cale: how does one define a 'salary field? the prime at the beginning denoting shared or something? |
| 05:31:58 | <ivanm> | and what does | row mean? |
| 05:32:14 | <Cale> | row is a variable representing the remainder of the fields in the record |
| 05:32:25 | <Cale> | So this expresses that it doesn't affect those |
| 05:32:49 | <ivanm> | and in the type sig, it means it's allowed to have other fields? |
| 05:32:56 | <Cale> | yes |
| 05:33:50 | <Cale> | These labels, distinguished by the fact that they start with ' and are not Char values, occur at both the value and type level. |
| 05:33:53 | <jfredett> | why would you need the | row at all then? if you have a record with one field -- I mean, it just seems pointless... :/ |
| 05:34:00 | <Cale> | and there would be various operations... |
| 05:34:22 | <ivanm> | Cale: "and are not Char values" <-- hmmm? |
| 05:34:32 | <Cale> | get 'salary rec :: { 'salary :: t | row } -> t |
| 05:34:42 | <Cale> | Well, 'a' :: Char |
| 05:34:50 | <ivanm> | ahhh, no closing quote |
| 05:34:52 | <Cale> | right |
| 05:35:03 | <ivanm> | jfredett: I guess it's the same as having a catch-all _ case in pattern matching |
| 05:35:32 | <Cale> | jfredett: In order to express where the rows move around when you have lots of records floating about |
| 05:35:36 | <jfredett> | but- i guess I'm trying to say- is there ever a case where you _wouldn't have the remainder there? |
| 05:35:51 | <Cale> | There would presumably be operations like record concatenation |
| 05:35:59 | <mmorrow> | hatds: i was trying to figure out how to use CallStack and came up with this http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5368#a5368 |
| 05:36:17 | <Cale> | jfredett: Yes, if you wanted to ensure there were no other fields. |
| 05:36:19 | <jfredett> | sure- but the `| row` doesn't appear to indicate ordering at all. |
| 05:36:44 | <mmorrow> | hatds: i'm still confused though about whether or not it's useful, because i can't figure out how to use it |
| 05:36:46 | <Cale> | Only the fields with the same name and type have an ordering (and act like a stack) |
| 05:36:54 | <Cale> | Otherwise, the fields are unordered. |
| 05:37:27 | <hatds> | mmorrow: reading your hpaste... but yea I'm having trouble since the place I wanted to use it needs to be able to perform IO |
| 05:37:45 | <mmorrow> | hatds: ooh, i was thinking about that, you could: |
| 05:37:53 | <Cale> | The stacklike behaviour may seem strange, but it means that you never have to worry about whether a record already has a field which you want to extend it with |
| 05:38:40 | <Cale> | (Some records systems require your types to contain predicates that some record lacks a given field, which seem more unnatural.) |
| 05:38:58 | <hatds> | mmorrow: actually I think I can modify my example to not use IO and it would still be 'useful', I can hpaste that for you |
| 05:39:14 | <Cale> | You'd have operations... |
| 05:40:04 | <Cale> | get :: (l :: Label) -> { l :: t | r } -> t |
| 05:40:15 | <Cale> | delete :: (l :: Label) -> { l :: t | r } -> { r } |
| 05:40:40 | <Cale> | extend :: (l :: Label) -> t -> { r } -> { l :: t | r } |
| 05:41:02 | <mmorrow> | hatds: arg, i was just trying to add a monad to it, but the Push (>>=) case is giving me trouble |
| 05:41:16 | <Cale> | put :: (l :: Label) -> t -> { l :: t | r } -> { l :: t | r } |
| 05:41:19 | <mmorrow> | hatds: cool, yeah |
| 05:41:33 | <jfredett> | wouldn't it be just put :: Label -> blahblah... |
| 05:41:38 | <jfredett> | rather than (l :: Label) ? |
| 05:41:45 | <Cale> | Label is the *kind* of l |
| 05:41:55 | <jfredett> | ... |
| 05:42:20 | <jfredett> | so- thats kind of like... dependent types? Kindof? |
| 05:42:24 | <Cale> | l is something at the type level, which is like a type having exactly one value with the same name, and you don't have to declare it |
| 05:42:34 | <jfredett> | interesting. |
| 05:42:41 | <Cale> | Similarly, the kind of r would be Row |
| 05:42:58 | <sjanssen> | Cale: "l :: Label" is a bit confusing as far as syntax |
| 05:43:02 | <Cale> | It wouldn't do for r to be something like Integer :) |
| 05:43:18 | <Cale> | Well, the kind could be inferred there |
| 05:43:28 | <Cale> | I was just being explicit |
| 05:43:35 | <sjanssen> | oh, it's a kind annotation. Makes a bit more sense when you think of that |
| 05:43:47 | <jfredett> | Sure, but do you really need a full type? I imagine all of this -- all of it could sit at the type level... |
| 05:43:56 | <jfredett> | I just don't see the need... :/ |
| 05:44:21 | <Cale> | Well, you have these things called labels which are like type-level values, so they should belong to a kind |
| 05:44:25 | <nimred> | wich way can i uninstall a package using cabal ? |
| 05:44:42 | <Cale> | You could just allow any type to act as a label, but that might be weird. |
| 05:44:57 | <sjanssen> | nimred: you can't actually uninstall. You can make GHC forget it exists with 'ghc-pkg unregister foo' |
| 05:45:11 | <Cale> | and it would require you to declare all your label-types by hand |
| 05:45:25 | <Cale> | (might be a good thing, but I think we can do without it) |
| 05:45:37 | <jfredett> | no- I mean- maybe I'm thinking to lispily, but have a datatype "label" which is a wrapper on string |
| 05:45:55 | <jfredett> | put (label "foo") ... |
| 05:45:56 | <Cale> | Oh, but Strings aren't available at compile time. |
| 05:46:04 | <jfredett> | ooh. |
| 05:46:06 | <Cale> | This is still statically checked. |
| 05:46:13 | <jfredett> | you are correct... |
| 05:46:27 | <nimred> | sjanssen and what about reinstall ? |
| 05:46:28 | <sjanssen> | Cale: the system you're describing is in some paper, who wrote it? |
| 05:46:38 | <jfredett> | sjanssen: good point. |
| 05:46:43 | <sjanssen> | nimred: reinstall is just installing it again |
| 05:47:43 | <Cale> | sjanssen: It's roughly the system which Daan Leijen described, but with minor changes in syntax |
| 05:48:45 | <sjanssen> | http://research.microsoft.com/en-us/um/people/daan/download/papers/scopedlabels.pdf |
| 05:48:50 | <Cale> | yeah |
| 05:49:16 | <jfredett> | excellent, more for the kindle. :) |
| 05:49:31 | <Cale> | He actually describes two similar but subtly different record systems in his two papers, but I haven't really made up my mind which I like better. |
| 05:50:04 | <sjanssen> | Cale: oh, interesting. I don't remember which I read |
| 05:50:36 | <nimred> | sjanssen ok thx |
| 05:50:43 | <Cale> | Also, while I like my 'lens-like' syntax idea, it's possible that a more general syntax for constructing records all at once is needed. |
| 05:50:57 | <Cale> | I really just don't like the use of . for field selection. |
| 05:51:30 | <sjanssen> | yeah, . is already overoverloaded |
| 05:51:51 | <Cale> | (If it had been me, we would have | for the module path separator) |
| 05:53:08 | <sjanssen> | interesting, Leijen's system also gives us variants |
| 05:53:13 | <Cale> | yes |
| 05:55:50 | <Cale> | Oh, actually, his first paper uses lacks predicates, which I don't care for so much. |
| 05:56:02 | <hatds> | mmorrow: hmm, I see a problem |
| 05:56:27 | <jfredett> | which paper am I reading here, it's the one sjanssen linked. |
| 05:56:36 | <hatds> | mmorrow: the way I intended to use this was with a function that takes an Event and runs the top thing on the call stack |
| 05:56:41 | <Cale> | You're reading the one which is closer to what I like then :) |
| 05:57:07 | <cads> | > :t curry |
| 05:57:07 | <hatds> | mmorrow: but you can't turn a "Return a" into a new, pop'ed callstack |
| 05:57:09 | <lambdabot> | <no location info>: parse error on input `:' |
| 05:57:20 | <jfredett> | okay, I'll happily follow along which your opinion, as it is most certainly better informed than mine. :) |
| 05:57:29 | <hatds> | mmorrow: I'll hpaste this to show you how I was envisioning of using it |
| 06:00:21 | <sohum> | so, I have a query. Could the compiler, when it notices that a function call doesn't typecheck, attempt to apply the appropriate liftM to the function, and accept that if it does typecheck? |
| 06:00:52 | <ivanm> | I doubt it |
| 06:00:56 | <Cale> | sohum: that would be confusing to do, but it could be done. |
| 06:01:10 | <Cale> | I wouldn't want it :) |
| 06:01:30 | <ski> | a type error isn't necessarily located to one place in the source |
| 06:01:35 | <sohum> | no? it seems as if that would simplify but only to the level of sugar writing monadic code |
| 06:03:08 | <hatds> | mmorrow: now if only I can get my hpaste to typecheck.. one sec :) |
| 06:03:20 | <Cale> | Well, blurring the lines between lifted and unlifted operations might seem like it would be convenient, but I think it makes the cases where both versions would typecheck a good bit more confusing... |
| 06:03:52 | <Cale> | You have to reason that something won't typecheck in order for the lifting to be there... |
| 06:04:41 | <sohum> | are there cases where both versions would typecheck? |
| 06:04:44 | <Cale> | yeah |
| 06:05:09 | <sohum> | oh, hm, I suppose there could be through typeclasses and such |
| 06:05:23 | <Cale> | > sequence [[[1,2,3], [4,5]], [[6,7,8], [9,10]]] |
| 06:05:25 | <lambdabot> | [[[1,2,3],[6,7,8]],[[1,2,3],[9,10]],[[4,5],[6,7,8]],[[4,5],[9,10]]] |
| 06:05:30 | <Cale> | > liftM sequence [[[1,2,3], [4,5]], [[6,7,8], [9,10]]] |
| 06:05:32 | <lambdabot> | [[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]],[[6,9],[6,10],[7,9],[7,10],[8,9],[8,... |
| 06:06:07 | <Cale> | (perhaps not too realistic an example, but probably more common ones exist too :) |
| 06:06:16 | <Cale> | Basically, anywhere that you have enough polymorphism |
| 06:06:41 | <sohum> | right |
| 06:06:45 | <cads> | for the type of curry, as defined by wikipedia :P, we have ::((A x B) -> C) -> (A -> (B -> C)). Knowing curry we see that that our curried function will take a value in A and return a partially applied function that takes a remaining value in C, and this is where I'm confused, the result seems to be a value in C, which doesn't give any insight into how curry worked for functions with more than two arguments |
| 06:07:05 | <Cale> | in B |
| 06:07:05 | <cads> | how do we write the type of the curry function in general? |
| 06:07:19 | <Cale> | curry f x y = f (x,y) |
| 06:07:28 | <Cale> | er |
| 06:07:34 | <Cale> | the type of it? |
| 06:07:38 | <Cale> | :t curry |
| 06:07:40 | <lambdabot> | forall a b c. ((a, b) -> c) -> a -> b -> c |
| 06:07:55 | <cads> | cale, yeah, the first "in C" should be "in B" |
| 06:08:19 | <Cale> | Currying functions of more arguments extends like... |
| 06:08:27 | <sohum> | huh, the haskell curry function splits apart pairs |
| 06:08:29 | <sohum> | cool. |
| 06:08:32 | <Cale> | :t let curry3 f x y z = f (x,y,z) in curry3 |
| 06:08:34 | <lambdabot> | forall t t1 t2 t3. ((t, t1, t2) -> t3) -> t -> t1 -> t2 -> t3 |
| 06:08:51 | <cads> | > (curry (/ x y z q -> (sum x y z q))) 1 2 3) |
| 06:08:53 | <lambdabot> | <no location info>: parse error on input `->' |
| 06:08:54 | <cads> | ack |
| 06:09:02 | <sohum> | lisp! |
| 06:09:03 | <cads> | > ((curry (/ x y z q -> (sum x y z q))) 1 2 3) 4) |
| 06:09:06 | <lambdabot> | <no location info>: parse error on input `->' |
| 06:09:10 | <Cale> | \ |
| 06:09:17 | <cads> | noooo, I'm forgetting haskell!!!!! |
| 06:09:23 | <Cale> | > ((curry (\x y z q -> (sum x y z q))) 1 2 3) 4) |
| 06:09:26 | <lambdabot> | <no location info>: parse error on input `)' |
| 06:09:28 | <cads> | sohum, your accusation was right! |
| 06:09:34 | <cads> | > ((curry (\ x y z q -> (sum x y z q))) 1 2 3) 4) |
| 06:09:36 | <cads> | lemme |
| 06:09:36 | <lambdabot> | <no location info>: parse error on input `)' |
| 06:09:44 | <cads> | > ((curry (\ x y z q -> (sum x y z q))) 1 2 3) 4 |
| 06:09:46 | <lambdabot> | Couldn't match expected type `[a]' against inferred type `(a1, b)' |
| 06:09:47 | <sohum> | twas not an accusation, my good man, but recognition! |
| 06:09:47 | <Cale> | I don't know which bracketing you want :) |
| 06:09:48 | <hatds> | mmorrow: okay http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5368#a5369 |
| 06:09:49 | <dmwit> | > curry (\x y z q -> sum [x, y, z, q]) (1, 2) 3 4 |
| 06:09:51 | <lambdabot> | Overlapping instances for GHC.Show.Show |
| 06:09:51 | <lambdabot> | (((t, ... |
| 06:09:55 | <dmwit> | :t curry |
| 06:09:57 | <lambdabot> | forall a b c. ((a, b) -> c) -> a -> b -> c |
| 06:10:10 | <hatds> | mmorrow: gonna go back to reading yours for the moment |
| 06:10:11 | <dmwit> | > curry (\(x, y) z q -> sum [x, y, z, q]) 1 2 3 4 |
| 06:10:13 | <lambdabot> | 10 |
| 06:10:46 | <Cale> | > (curry . curry) (\((x,y),z) q -> sum [x,y,z,q]) 1 2 3 4 |
| 06:10:49 | <lambdabot> | 10 |
| 06:10:58 | <Cale> | > (curry . curry . curry) (\(((x,y),z),q) -> sum [x,y,z,q]) 1 2 3 4 |
| 06:11:00 | <lambdabot> | 10 |
| 06:11:12 | <dmwit> | Also, q? |
| 06:11:17 | <dmwit> | How about w x y z instead. =P |
| 06:11:31 | <cads> | hey man, it's late |
| 06:11:45 | <cads> | this bugs me, I always thought curry could do |
| 06:12:12 | <cads> | > (((curry (\ (x, y, z, q) -> sum [x y z q])) 1) 2 3) 4 |
| 06:12:14 | <lambdabot> | Couldn't match expected type `(a, b)' |
| 06:12:17 | <Cale> | nope |
| 06:12:20 | <dmwit> | :t curry4 |
| 06:12:22 | <lambdabot> | Not in scope: `curry4' |
| 06:12:27 | <cads> | haha |
| 06:12:29 | <cads> | really? |
| 06:12:32 | <dmwit> | nope |
| 06:12:40 | <Cale> | @let curry4 f w x y z = f (w,x,y,z) |
| 06:12:43 | <lambdabot> | Defined. |
| 06:12:55 | <Cale> | > curry4 (\ (x, y, z, q) -> sum [x y z q]) 1 2 3 4 |
| 06:12:57 | <lambdabot> | Add a type signature |
| 06:13:01 | <dmwit> | commas |
| 06:13:15 | <Cale> | > curry4 (\ (x, y, z, q) -> sum [x, y, z, q]) 1 2 3 4 |
| 06:13:17 | <lambdabot> | 10 |
| 06:13:20 | <dmwit> | > curry4 (\(w, x, y, z) -> sum [w x y z]) id id id 4 |
| 06:13:22 | <lambdabot> | 4 |
| 06:13:26 | <Cale> | haha |
| 06:13:37 | <Cale> | good call |
| 06:13:41 | <cads> | aw well, they curry function I've been playing with in my head was a bit muddled because I didn't think about tuples |
| 06:14:05 | <Cale> | Tuples are all separate types in Haskell, so there's no one curry function which will handle them all |
| 06:14:24 | <cads> | I think it's stronger that normal curry, but its type depends on the function you give it |
| 06:14:37 | <Cale> | normal curry? |
| 06:14:50 | <cads> | yeah, that weak stuff you buy in packets |
| 06:14:53 | <Cale> | hehe |
| 06:15:00 | <cads> | this curry will blow your socks off |
| 06:15:09 | <Cale> | and then there's uncurry |
| 06:15:19 | <Cale> | uncurry is to pairs what foldr is to lists |
| 06:15:32 | <sohum> | :t uncurry |
| 06:15:33 | <cads> | :type uncurry |
| 06:15:34 | <lambdabot> | forall a b c. (a -> b -> c) -> (a, b) -> c |
| 06:15:39 | <Cale> | > uncurry (\x y -> x + y) (3,5) |
| 06:15:41 | <lambdabot> | 8 |
| 06:15:49 | <cads> | yeah, I like uncurry |
| 06:16:15 | <Cale> | maybe is another one of this family of functions |
| 06:16:18 | <Cale> | :t maybe |
| 06:16:20 | <lambdabot> | forall b a. b -> (a -> b) -> Maybe a -> b |
| 06:16:24 | <cads> | man, functional programming without the type system there to show you what you did is tough |
| 06:16:36 | <Cale> | :t either |
| 06:16:38 | <lambdabot> | forall a c b. (a -> c) -> (b -> c) -> Either a b -> c |
| 06:16:48 | <Cale> | :t foldr |
| 06:16:50 | <lambdabot> | forall a b. (a -> b -> b) -> b -> [a] -> b |
| 06:17:16 | <Cale> | The similarity here is that they take a parameter which serves as a replacement for each of the constructors of the datatype |
| 06:17:26 | <Cale> | and a value of that type |
| 06:17:34 | <Cale> | and make the replacements throughout |
| 06:17:53 | <Gracenotes> | lthough, list is a recursive datatype. |
| 06:17:54 | <Gracenotes> | a |
| 06:17:56 | <Cale> | right |
| 06:18:02 | <sohum> | incidentally |
| 06:18:07 | <sohum> | is there a List typeclass? |
| 06:18:09 | <Gracenotes> | so why foldr and not foldl? Because foldr folds "along" a list? |
| 06:18:23 | <hatds> | mmorrow: yea, I think it needs to be a list-like structure, but maybe Push isn't the only cons operator, what if Return is also cons-like? |
| 06:18:27 | <sohum> | that say : and the [x:xs] destructuring is defined in terms of? |
| 06:18:34 | <Gracenotes> | whereas foldl just takes an accumulator as you go |
| 06:18:59 | <Cale> | Gracenotes: foldl does a more complicated structural transformation |
| 06:19:04 | <Cale> | I have some diagrams... |
| 06:19:11 | <Gracenotes> | yeah :) |
| 06:19:12 | <Cale> | http://cale.yi.org/index.php/Fold_Diagrams |
| 06:19:19 | <Gracenotes> | ACTION has it bookmarked |
| 06:19:27 | <Gracenotes> | I see |
| 06:19:29 | <ray> | wikipedia has about half those diagrams |
| 06:19:36 | <ray> | er, not half |
| 06:19:48 | <Cale> | Right, I wrote 90% of the wikipedia article on folds |
| 06:20:08 | <ray> | i figured you either wrote or rewrote it when i saw those |
| 06:20:34 | <Cale> | Well, what was there before was almost complete garbage, so I rewrote it. |
| 06:21:35 | <sohum> | hahaha, nice |
| 06:21:41 | <sohum> | crowdsourcing fte) |
| 06:21:44 | <sohum> | *ftw |
| 06:21:49 | <Gracenotes> | it probably helps to have a CT understand of folds |
| 06:22:07 | <Gracenotes> | they are everywhere. even in set theory, you have k-folds via union/intersection... |
| 06:22:12 | <cads> | forgetting about laziness, there's a difference between a left and right fold only iff the function you're folding the list over does not commute, right? |
| 06:22:23 | <Cale> | Oh, there's a new language comparison table there :) |
| 06:22:43 | <cads> | Gracenotes: even a union is a fold? |
| 06:23:02 | <Gracenotes> | I think you could consider a big union a fold of unions |
| 06:23:12 | <cads> | certainly |
| 06:23:17 | <ray> | they're different if it doesn't commute, but i'm not sure about iff |
| 06:23:36 | <cads> | no it's not iff, sorry |
| 06:24:00 | <cads> | they can be the same even if f doesn't commute in general |
| 06:24:23 | <Gracenotes> | I'm pretty sure associative is required though, hmm? |
| 06:24:42 | <Gracenotes> | I've wondered about the class of operators for which left fold == right fold... |
| 06:24:50 | <cads> | it just has to have the right type |
| 06:25:26 | <Gracenotes> | if foldl f z xs compiles, foldr (flip f) z xs will compile. so type isn't so hard... |
| 06:26:03 | <copumpkin> | commutative? |
| 06:26:13 | <copumpkin> | if you want foldl to equal foldr? |
| 06:26:15 | <dmwit> | > foldr f z [x, y, z] |
| 06:26:17 | <lambdabot> | Ambiguous occurrence `f' |
| 06:26:17 | <lambdabot> | It could refer to either `L.f', defined at <local... |
| 06:26:25 | <dmwit> | > foldr g z [x, y, z] |
| 06:26:27 | <lambdabot> | Ambiguous occurrence `g' |
| 06:26:27 | <lambdabot> | It could refer to either `L.g', defined at <local... |
| 06:26:31 | <dmwit> | booo |
| 06:26:36 | <copumpkin> | @undefine |
| 06:26:41 | <dmwit> | > foldr f z [x, y, z] |
| 06:26:43 | <lambdabot> | f x (f y (f z z)) |
| 06:26:46 | <dmwit> | > foldl (flip f) z [x, y, z] |
| 06:26:48 | <lambdabot> | f z (f y (f x z)) |
| 06:26:59 | <copumpkin> | zomg noes |
| 06:26:59 | <Gracenotes> | copumpkin: for all input, yes |
| 06:27:03 | <dmwit> | Oh, let's try that again, with less z's this time. |
| 06:27:07 | <Gracenotes> | finite input, let's say, to keep it simple |
| 06:27:20 | <dmwit> | > (foldr f z [w, x, y], foldl (flip f) z [w, x, y]) |
| 06:27:22 | <lambdabot> | (f w (f x (f y z)),f y (f x (f w z))) |
| 06:27:30 | <Gracenotes> | works for (+) for instance |
| 06:27:45 | <dmwit> | Looks like it has to be at least commutative. |
| 06:28:04 | <Gracenotes> | there may be non-commutative though. I'm not quite sure :) |
| 06:28:14 | <copumpkin> | well since it's going in the opposite "direction" |
| 06:28:26 | <copumpkin> | it's going to take a lot of "commutation" to get it back into the right direction :) |
| 06:28:31 | <dmwit> | > (foldr f z [x, y], foldl (flip f) [x, y]) |
| 06:28:33 | <copumpkin> | seems like that's all that's needed though |
| 06:28:33 | <lambdabot> | No instance for (SimpleReflect.FromExpr [SimpleReflect.Expr]) |
| 06:28:33 | <lambdabot> | arising fr... |
| 06:28:37 | <cads> | I think it needs to be associative as well. Given the commutativity, it seems like if foldl f a = foldr f a, f::a->a->a |
| 06:28:38 | <dmwit> | > (foldr f z [x, y], foldl (flip f) z [x, y]) |
| 06:28:40 | <lambdabot> | (f x (f y z),f y (f x z)) |
| 06:29:08 | <copumpkin> | oh yeah, I meant in addition to the associativity that Gracenotes mentioned earlier |
| 06:29:14 | <dmwit> | Gracenotes: Well, if the function has any fixed-point, the above proves that it must also be commutative for left- and right-folds to be equal. |
| 06:29:39 | <Gracenotes> | a fix-point? on two parameters? |
| 06:29:50 | <dmwit> | duh, I mean identity |
| 06:29:51 | <copumpkin> | > foldr (+) 0 (replicate 1000 0.01) |
| 06:29:52 | <lambdabot> | 9.999999999999831 |
| 06:29:55 | <copumpkin> | > foldl (+) 0 (replicate 1000 0.01) |
| 06:29:57 | <lambdabot> | 9.999999999999831 |
| 06:30:10 | <copumpkin> | not associative? |
| 06:30:23 | <Gracenotes> | hm |
| 06:30:31 | <copumpkin> | not sure that counts as a proof though ;) |
| 06:30:34 | <Gracenotes> | someone needs to write a proof or something! not it. |
| 06:30:56 | <Gracenotes> | I'll see if there's anything online... |
| 06:31:10 | <dmwit> | copumpkin: If it's not commutative, there is x and y such that f x y /= f y x. Taking z to be the identity, then f x (f y z) /= f y (f x z). QED |
| 06:31:25 | <copumpkin> | hmm? |
| 06:31:31 | <copumpkin> | I wasn't questioning the commutativity |
| 06:31:33 | <dmwit> | oh |
| 06:31:34 | <dmwit> | heh |
| 06:31:40 | <copumpkin> | the associativity though? |
| 06:32:00 | <copumpkin> | I don't think it needs it |
| 06:32:03 | <dmwit> | Yeah, I'm not sure I see where associativity comes in, either. |
| 06:32:47 | <dmwit> | Quick! Somebody think of a function that's commutative but not associative. |
| 06:32:57 | <copumpkin> | floating point addition :P |
| 06:33:33 | <dmwit> | prove it |
| 06:33:42 | <dmwit> | No, don't bother. |
| 06:33:48 | <dmwit> | It's not helpful the way I thought it would be. |
| 06:34:09 | <Cale> | Floating point addition is not associative |
| 06:34:14 | <dmwit> | I know. |
| 06:34:23 | <Gracenotes> | I saw this: http://portal.acm.org/citation.cfm?id=156301.156303 |
| 06:34:28 | <dmwit> | I was just asking for a specific example that shows off that fact. =) |
| 06:34:31 | <copumpkin> | @check \x y z -> (x + y) + z == (x :: Float) + (y + z) |
| 06:34:32 | <Gracenotes> | "when floating-point addition isn't commutative" |
| 06:34:32 | <lambdabot> | "Falsifiable, after 11 tests:\n-1.6\n1.8\n4.5\n" |
| 06:34:54 | <Gracenotes> | unfortunately it's ACM, so... *arghhhhhhh darn you ACM* |
| 06:35:05 | <copumpkin> | you don't have access? |
| 06:35:08 | <Cale> | Oh, when foldr f z and foldl f z are equal? Well, a sufficient condition is for f and z to give a monoid. |
| 06:35:24 | <copumpkin> | really? |
| 06:35:26 | <copumpkin> | hmm |
| 06:35:27 | <Cale> | yes |
| 06:35:28 | <Gracenotes> | Cale: iff? |
| 06:35:28 | <dmwit> | Yeah, but that's too much. |
| 06:35:36 | <dmwit> | Because monoids are associative. |
| 06:35:40 | <Cale> | Obviously it's not a necessary condition. |
| 06:35:45 | <dmwit> | I don't think associativity is necessary. |
| 06:35:47 | <Cale> | Associativity is important. |
| 06:35:54 | <dmwit> | oh? |
| 06:36:05 | <Cale> | That's most of the difference between the two |
| 06:36:05 | <Gracenotes> | and there's also: foldr f z vs. foldl (flip f) z, which allows list type != accumulator type in comparison |
| 06:36:21 | <Cale> | The only other difference is that they put the z on opposite ends |
| 06:36:48 | <dmwit> | Wait, hold up a tick: are we comparing foldr f and foldl f, or foldr f and foldl (flip f)? |
| 06:36:54 | <Cale> | But I don't think there's a nice necessary+sufficient condition. |
| 06:37:01 | <dmwit> | For the former, I could believe associativity matters; for the latter, not so much. |
| 06:37:12 | <Cale> | foldr f z and foldl f z |
| 06:37:23 | <Gracenotes> | > (foldl (-) 0 [1..100], foldr subtract 0 [1..100]) |
| 06:37:25 | <lambdabot> | (-5050,-5050) |
| 06:37:28 | <Cale> | foldl (flip f) z is like foldr f z . reverse |
| 06:37:47 | <Gracenotes> | Cale: yes... |
| 06:38:09 | <Gracenotes> | hm. So if f is commutative, that might be an easier condition... |
| 06:38:14 | <Cale> | wait... |
| 06:38:23 | <Cale> | > foldl (flip f) z [1,2,3,4,5] |
| 06:38:25 | <lambdabot> | f 5 (f 4 (f 3 (f 2 (f 1 z)))) |
| 06:38:37 | <Cale> | right, yes |
| 06:39:05 | <Cale> | But for the other way, f being commutative doesn't help. |
| 06:39:23 | <Cale> | hmm |
| 06:40:58 | <mmorrow> | , foldr (.) id [f,f,f,f] x |
| 06:41:00 | <lunabot> | f (f (f (f x))) |
| 06:41:04 | <mmorrow> | , foldl (flip id) x [f,f,f,f] |
| 06:41:07 | <lunabot> | f (f (f (f x))) |
| 06:41:19 | <copumpkin> | cheat0r |
| 06:41:28 | <mmorrow> | z0mg |
| 06:42:21 | <dmwit> | , foldr ($) x [f, f, f, f] |
| 06:42:23 | <lunabot> | f (f (f (f x))) |
| 06:42:51 | <dmwit> | , iterate f x !! 4 |
| 06:42:54 | <lunabot> | f (f (f (f x))) |
| 06:43:18 | <copumpkin> | , f (f (f (f x))) |
| 06:43:20 | <lunabot> | luna: Ambiguous type variable `a' in the constraints: |
| 06:43:24 | <copumpkin> | ACTION fails :) |
| 06:43:29 | <copumpkin> | , f (f (f (f x))) :: Expr |
| 06:43:31 | <lunabot> | luna: Ambiguous type variable `t' in the constraints: |
| 06:43:38 | <copumpkin> | ACTION fails again |
| 06:43:56 | <mmorrow> | ah yeah, that's annoying |
| 06:44:02 | <mmorrow> | , fix (h . g . f) |
| 06:44:04 | <lunabot> | luna: Ambiguous type variable `c' in the constraints: |
| 06:44:09 | <mmorrow> | , fix ((h::Expr->Expr) . g . f) |
| 06:44:10 | <lunabot> | luna: Ambiguous type variable `b' in the constraints: |
| 06:44:12 | <copumpkin> | failuna |
| 06:44:15 | <mmorrow> | , fix ((h::Expr->Expr) . (g::Expr->Expr) . f) |
| 06:44:17 | <lunabot> | h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h... |
| 06:44:36 | <mmorrow> | you can't have more than one 'f' (or whatever) "in a row" |
| 06:44:41 | <mmorrow> | without an annotation |
| 06:45:00 | <Gracenotes> | because FromExpr is just Expr a => (Expr -> a) |
| 06:45:05 | <mmorrow> | i think it's for the same reason that (read . show) doesn't work |
| 06:45:09 | <mmorrow> | yeah |
| 06:45:19 | <Gracenotes> | er. s/Expr/FromExpr/g |
| 06:45:40 | <Gracenotes> | actually, more general than I thought. (Show a, FromExpr b) => FromExpr (a -> b) |
| 06:46:19 | <mmorrow> | @type [($),id] |
| 06:46:20 | <lambdabot> | forall a b. [(a -> b) -> a -> b] |
| 06:46:36 | <Gracenotes> | > f (Just "hello there") :: Expr |
| 06:46:37 | <lambdabot> | f (Just "hello there") |
| 06:46:39 | <mmorrow> | foldr ($) === foldl (flip id) |
| 06:47:01 | <mmorrow> | (at least wrt the result) |
| 06:47:17 | <mmorrow> | err, s/result/type/ |
| 06:47:31 | <cads> | we have 1) (((a* + a) + b) + c). I don't think we can we transform 2) ((a* + c) + b) + a) into 1) unless + is both assoc and commie. Using associativity lets us rewrite this as (a* + c + b + a). Using commutativity allows us to rewrite 2) to (a + (b + (a* + c))), but to break the a* out and bring it to the front, we need assoc |
| 06:47:35 | <mmorrow> | (and foldr ($) = foldr id ;) |
| 06:48:37 | <mmorrow> | the thing with fold direction too is (i've wondered how to say without hand-waving) that you usually (always?) want to fold in the direction of an op's fixity |
| 06:48:50 | <mmorrow> | , src '(.) |
| 06:48:53 | <lunabot> | ) :: forall b c a . (b -> c) -> (a -> b) -> a -> c |
| 06:48:53 | <lunabot> | infixr 9 ) |
| 06:48:58 | <mmorrow> | :o |
| 06:49:15 | <Cale> | > fix (\g -> (1:) . g) [] |
| 06:49:18 | <lambdabot> | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,... |
| 06:49:20 | <mmorrow> | infix infixr 5 ++ |
| 06:49:22 | <Cale> | > fix (\g -> g . (1:)) [] |
| 06:49:30 | <lambdabot> | mueval-core: Prelude.read: no parse |
| 06:49:30 | <lambdabot> | mueval: ExitFailure 1 |
| 06:49:42 | <dmwit> | > fromExpr "hey" x |
| 06:49:46 | <lambdabot> | Not in scope: `fromExpr' |
| 06:50:50 | <mmorrow> | hatds: hmm, i played with it a little more, but i feel like every time i write an expression that uses Push, the Pushes are just extraneous |
| 06:50:51 | <Cale> | mmorrow: That's because people choose the fixity the same way they'd choose a fold, because a left fold produces a left-associated expression and a right fold produces a right associated one :) |
| 06:51:01 | <mmorrow> | Cale: heh, good point |
| 06:51:02 | <cads> | fixpoints are kind of ungodly powerful |
| 06:51:15 | <mmorrow> | Cale: self-fulfilling prophecyish |
| 06:52:21 | <Gracenotes> | > fun "Hello there" "person" :: Expr |
| 06:52:23 | <lambdabot> | Hello there "person" |
| 06:52:37 | <dmwit> | cads: Yep, anything you can do with recursion... |
| 06:53:59 | <mmorrow> | fix === a while(1), a single var, and the ability to break or continue.. |
| 06:55:14 | <cads> | dmwit, even elsewhere. For example the fixpoint theorem from metric spaces in analysis lets you do some sick stuff as far as proving the existance of solutions to some crazy integral equations and other things |
| 06:55:30 | <mmorrow> | well, it's more i guess kinda |
| 06:55:48 | <mmorrow> | , fix (\x -> Node () [x,x]) {- self-referent structures -} |
| 06:55:50 | <lunabot> | Node {rootLabel = (), subForest = [Node {rootLabel = (), subForest = [Nod... |
| 06:56:20 | <Gracenotes> | mmorrow: hm... not so sure about that? |
| 06:56:27 | <mmorrow> | void *xs[2]; xs[0] = xs; xs[1] = xs; |
| 06:56:33 | <cads> | using fixed points and their properties we can write out a very nice computability theory, too |
| 06:56:49 | <mmorrow> | Gracenotes: about what? |
| 06:56:50 | <Gracenotes> | you can have recursive fib with fixpoint after all. It is really just recursion. not sure if it's general, but I woudln't be surprised... |
| 06:58:49 | <mmorrow> | i don't understand |
| 06:59:19 | <mmorrow> | int x[] = {0,1}; int tmp; while(1){printf("%d\n",x[0]); tmp = x[0]; x[0] = x[1]; x[1] += tmp;} |
| 06:59:35 | <mmorrow> | , fix (\k m n -> m : k n (m+n)) 0 1 |
| 06:59:36 | <lunabot> | [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,109... |
| 07:00:13 | <Gracenotes> | mmorrow: that's not recursive fib :) |
| 07:00:20 | <mmorrow> | but doing "void *xs[2]; xs[0] = xs; xs[1] = xs;" is kinda a different concept than a while loop |
| 07:00:29 | <mmorrow> | Gracenotes: it's recursing :) |
| 07:00:30 | <Cale> | Gracenotes: But it sort of is... |
| 07:00:53 | <Cale> | fix f = x where x = f x |
| 07:01:00 | <Cale> | So... |
| 07:01:05 | <Cale> | fix (\k m n -> m : k n (m+n)) 0 1 |
| 07:01:39 | <Cale> | = x 0 1 where x = (\k m n -> m : k n (m+n)) x |
| 07:01:55 | <Cale> | = x 0 1 where x = \m n -> m : x n (m+n) |
| 07:01:58 | <Gracenotes> | > fix (\k b -> if b <= 1 then b else k (b - 1) + k (b - 2)) 10 |
| 07:01:59 | <lambdabot> | 55 |
| 07:02:03 | <Cale> | = x 0 1 where x m n = m : x n (m+n) |
| 07:02:57 | <cads> | http://aclinks.wordpress.com/ how to become a successful researcher :D |
| 07:03:09 | <mmorrow> | Gracenotes: you can do that with a while loop too, you just have to maintain your own call stack |
| 07:03:15 | <Gracenotes> | you can do branching recursion, it seems. probably even ackermann |
| 07:03:17 | <cads> | a talk by peyton jones on the subject is listed there, that ought to be entertaining |
| 07:03:32 | <Gracenotes> | which is just about as primitive-recursive-y as you can go |
| 07:03:36 | <mmorrow> | Gracenotes: err, fix is general recursion |
| 07:03:37 | <Cale> | Gracenotes: You can write *all* recursion in terms of fix |
| 07:03:57 | <cads> | can't fix do corecursion and junk? |
| 07:03:59 | <Gracenotes> | mmorrow: okay, why didn't you say so? :) |
| 07:04:20 | <mmorrow> | Gracenotes: heh, i didn't know what you were saying until just now |
| 07:04:30 | <Gracenotes> | you can write all recursion in terms of while(1) too, although when you need an explicit call stack... hrm |
| 07:04:39 | <Gracenotes> | as you just said |
| 07:05:03 | <Gracenotes> | just not tail recursive then. |
| 07:05:05 | <mmorrow> | well, you need the stack if you want to write it in the same style |
| 07:05:26 | <mmorrow> | you can always transform it i guess (maybe) |
| 07:06:02 | <cads> | if we have f = g . f for nonrecursive g, then doesn't f = fix g ? |
| 07:06:07 | <mmorrow> | as in, just compute it bottom-up |
| 07:06:19 | <Gracenotes> | @free fix |
| 07:06:22 | <lambdabot> | f . g = h . f => f (fix g) = fix h |
| 07:06:23 | <mmorrow> | like that bottom-up fib |
| 07:07:13 | <cads> | Gracenotes: so yes, neat |
| 07:07:30 | <Gracenotes> | hm... for what values of f, g, and h does it == your theorem? |
| 07:08:20 | <cads> | the rolling theorem is neat too fix (f . g) = g (fix (g . f)) |
| 07:08:23 | <Gracenotes> | (of course both may be independant) |
| 07:08:45 | <Gracenotes> | cads: ooh, that's neat f . g . f . g . f . g |
| 07:09:00 | <Cale> | if we put g = id, then we get if f = h . f then f (fix id) = fix h |
| 07:09:20 | <mmorrow> | , fix ((h::Expr->Expr) . (g::Expr->Expr) . f) {- never gets old -} |
| 07:09:22 | <lunabot> | h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h (g (f (h... |
| 07:09:24 | <cads> | thanks cale |
| 07:09:42 | <Cale> | Which means that f = const (fix h) |
| 07:09:55 | <Gracenotes> | hm |
| 07:10:53 | <Cale> | cads: Not f (fix (g . f)) ? |
| 07:11:16 | <Cale> | > fix ((1:) . (2:)) |
| 07:11:18 | <lambdabot> | [1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,... |
| 07:11:31 | <Cale> | > (1:) (fix ((2:) . (1:))) |
| 07:11:33 | <lambdabot> | [1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,... |
| 07:11:58 | <cads> | hrm |
| 07:12:28 | <thomastc> | lambdabot: can Haskell take over the world? |
| 07:12:46 | <Cale> | @faq can Haskell take over the world? |
| 07:12:47 | <lambdabot> | The answer is: Yes! Haskell can do that. |
| 07:13:07 | <thomastc> | ah, confused with syntax of other bot, thanks :) |
| 07:14:05 | <mmorrow> | , fix ((0:) . scanl (+) 1) |
| 07:14:07 | <lunabot> | [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,109... |
| 07:14:11 | <cads> | ahh, cale, (f . g . f . g ...) = f (g . f . g ...), you're right; f is the "last" function we apply before our point is fixed. We can pull it out, and roll over the variables |
| 07:14:19 | <cads> | err, functions |
| 07:14:26 | <Cale> | cads: yeah |
| 07:14:37 | <Cale> | Or the first |
| 07:14:45 | <Cale> | Depending on the way you look at it |
| 07:15:28 | <cads> | grr, I wish I knew function composition like I knew addition and multiplication |
| 07:15:31 | <Cale> | ACTION is geared to thinking of evaluation as being outermost-first |
| 07:19:12 | <copumpkin> | fail: http://shootout.alioth.debian.org/u64q/benchmark.php?test=regexdna&lang=ghc&id=4 |
| 07:25:12 | <cads> | Let's say a corecursive function fixes after a few iterations, like 1) (f . g . f . g) = g (f . g . f . g). Then obviously 2) f (g . f . g) is the same thing as the lhs of 1). But then 1) = fix(f . g) = 2) = f . (fix (g . f)). This is true for functions which fix in a given number of recursion, and for functions that fix in a number of recursions greater than that. I think there are a few holes, but QED. |
| 07:25:18 | <cads> | hehe, I need to go to bed |
| 07:25:31 | <cads> | take care all |
| 07:26:22 | <cads> | ACTION handwaves all the way to bed |
| 07:28:55 | <copumpkin> | night :) |
| 07:39:52 | <copumpkin> | is a unitary matrix positive definite? |
| 07:42:57 | <Raynes> | ACTION huggles copumpkin |
| 07:44:16 | <ivanm> | "huggles"? |
| 07:44:35 | <copumpkin> | ACTION huggles ivanm and Raynes |
| 07:44:50 | <ivanm> | stay away from me! |
| 07:45:01 | <Raynes> | ivanm: It's a word used by sophisticated IRC/Haskellers. |
| 07:45:20 | <ivanm> | ACTION quickly builds a barrier out of handy objects, furniture, people, etc. to protect against copumpkin |
| 07:45:37 | <ivanm> | Raynes: since when did "sophisticated" imply "can't use normal English words"? |
| 07:45:54 | <olsner> | ivanm: hasn't that always been the case? |
| 07:46:06 | <ivanm> | not that I know of |
| 07:46:17 | <^Someone^> | "normal"? |
| 07:46:19 | <Raynes> | ivanm: Since I invented the word glaseymaster. |
| 07:46:24 | <copumpkin> | Raynes: there's a @spam twitter account btw |
| 07:46:49 | <Raynes> | To report spammers? |
| 07:46:52 | <Raynes> | Neato. |
| 07:46:58 | <ivanm> | ^Someone^: normal, as in words that already exist, etc. |
| 07:47:05 | <^Someone^> | "huggles" does exist |
| 07:47:29 | <hackagebot> | explicit-sharing 0.4.0 |
| 07:47:30 | <ivanm> | Raynes: oh, I would have thought it would have been to get your daily fix of spam... |
| 07:47:34 | <^Someone^> | It's recently been added to the dictionary too |
| 07:47:38 | <ivanm> | ^Someone^: formally? |
| 07:47:45 | <ivanm> | ACTION checks his dictionaries |
| 07:48:02 | <^Someone^> | Yes |
| 07:48:48 | <ivanm> | I can't find it in the copy of the Pocket Oxford Dictionary I have handy |
| 07:48:55 | <ivanm> | but there is "hugger-mugger" :s |
| 07:49:11 | <^Someone^> | Somewhat recently -_- |
| 07:49:19 | <^Someone^> | Anyway! |
| 07:49:23 | <^Someone^> | That's not the point |
| 07:49:52 | <^Someone^> | The point is that it makes sense to create and use such a word |
| 07:51:06 | <^Someone^> | Especially for a functional programmer, I should think : o |
| 07:51:31 | <ivanm> | it does? |
| 07:51:35 | <ivanm> | in what way? |
| 07:51:38 | <^Someone^> | It's almost like function composition |
| 07:51:42 | <ivanm> | since I have no idea wtf it means... >_> |
| 07:51:59 | <^Someone^> | It's a hug and a snuggle combined |
| 07:52:09 | <ivanm> | *shudder* |
| 07:52:38 | <ivanm> | function composition -/-> "making up new words by juxtapositioning one word upon another" |
| 07:52:47 | <^Someone^> | "almost like" |
| 07:53:35 | <copumpkin> | huggle = hug . cuddle |
| 07:53:39 | <ivanm> | *usage of function composition |
| 07:53:53 | <ivanm> | copumpkin: that makes even less sense than ^Someone^'s definition |
| 07:54:08 | <ivanm> | and it goes to show, that if you can't even decide what your made-up words mean, then we shouldn't be using them! |
| 07:54:18 | <copumpkin> | who says it isn't an overloaded word? |
| 07:54:22 | <copumpkin> | language are full of them |
| 07:54:28 | <copumpkin> | *languages |
| 07:54:32 | <ivanm> | heh |
| 07:54:43 | <olsner> | "portmonteau" is a nice term that I think might apply to 'huggle' |
| 07:55:01 | <dmwit> | ?wn portmanteau |
| 07:55:03 | <lambdabot> | *** "portmanteau" wn "WordNet (r) 2.0" |
| 07:55:03 | <lambdabot> | portmanteau |
| 07:55:03 | <lambdabot> | n 1: a new word formed by joining two others and combining their |
| 07:55:03 | <lambdabot> | meanings; "`smog' is a blend of `smoke' and `fog'"; |
| 07:55:03 | <lambdabot> | "`motel' is a portmanteau word made by combining `motor' |
| 07:55:05 | <lambdabot> | [5 @more lines] |
| 07:55:08 | <dmwit> | Your spelling sucks, but your vocabulary is impeccable. |
| 07:55:12 | <copumpkin> | besides, it may just be a proof that snuggle == cuddle assuming hug is a monomorphism |
| 07:55:14 | <ivanm> | class Definition ^Someone^ where huggle = hug . snuggle; class Definition copumpkin where huggle = hug . cuddle |
| 07:55:15 | <ivanm> | ;-) |
| 07:55:19 | <^Someone^> | Yes, the words were MELDed together |
| 07:55:21 | <^Someone^> | ; ) |
| 07:55:25 | <ivanm> | olsner: no, IIRC portmanteau means they just join them together |
| 07:55:28 | <^Someone^> | Like Melt and weld xD |
| 07:55:41 | <ivanm> | whereas both ^Someone^ and copumpkin have dropped intermediary letters |
| 07:55:45 | <copumpkin> | ACTION wonders if he used monomorphism correctly there |
| 07:56:09 | <copumpkin> | ACTION is still reading awodey |
| 07:56:29 | <dmwit> | I think you used it correctly. |
| 07:56:44 | <dmwit> | The only other choice is epimorphism, but it's not that. =) |
| 07:56:58 | <copumpkin> | I prefer to call it an epic morphism win |
| 07:57:13 | <ivanm> | dmwit: hmmm, maybe he did |
| 07:58:12 | <mornfall> | ivanm: "just joining" is juxtaposition, portmanteau is smacking them together at high speed. ;) |
| 07:58:26 | <ivanm> | *nod* |
| 07:58:42 | <ski> | forall A,B. forall f : A -> B. mono f <=> forall T. forall x,y : T -> A. f . x = f . x => x = y |
| 07:58:43 | <ivanm> | ahhh, I used the wrong term |
| 07:58:45 | <copumpkin> | epic word fusion |
| 07:58:56 | <copumpkin> | I mean monic |
| 07:58:57 | <ivanm> | not juxtaposition.... which word means you put one on top of the other? |
| 07:58:57 | <copumpkin> | ;) |
| 07:58:58 | <Gracenotes> | o nos |
| 07:59:35 | <mornfall> | ivanm: overlay maybe? |
| 07:59:45 | <ivanm> | maybe |
| 08:00:00 | <ivanm> | there's a semi-technical term though... *shrug* not that big a deal |
| 08:00:12 | <dmwit> | superposition? |
| 08:00:17 | <osfameron> | superimpose? |
| 08:00:17 | <mornfall> | Like jumbled printing? : - ) |
| 08:00:17 | <dmwit> | But that's not really the same. |
| 08:00:38 | <mornfall> | Sounds perfectly technical to me. |
| 08:00:49 | <ivanm> | dmwit: that's the one |
| 08:00:57 | <ivanm> | that's what I was thinking of, anyway |
| 08:01:26 | <ski> | ACTION . o O ( M-x dissociated-press ) |
| 08:02:09 | <olsner> | ski executes the dissociated press? |
| 08:02:13 | <mornfall> | Err. --> bassoon, anyway. Cya. :) |
| 08:02:49 | <ivanm> | ski: hmmmm, my version of emacs doesn't have that function |
| 08:02:57 | <ivanm> | is it from an external elisp file? |
| 08:04:45 | <ski> | `dissociate.el' according to <http://en.wikipedia.org/wiki/Dissociated_press> |
| 08:17:15 | <dancor_> | i want to be able to sequentially modify all the occurrences of the datatype Expr in my Stmt datatype |
| 08:17:31 | <dancor_> | it sounds like Traversable, but it's complicated by having a second type i think |
| 08:22:30 | <ski> | Detect Loop <http://www.getacoder.com/projects/detect_loop_106243.html> |
| 08:23:27 | <dmwit> | troll |
| 08:23:37 | <dmwit> | Hint #1: username is fermat. |
| 08:23:44 | <dcoutts> | ski: no problem, so long as they don't mind occasionally getting "dunno" as the answer |
| 08:27:09 | <ski> | dancor_ : "complicated by having a second type" ? |
| 08:27:34 | <WorkyBob> | ski: hehe, that one is fun |
| 08:27:42 | <copumpkin> | halting is decidable on LBAs anyway isn't it? |
| 08:27:59 | <dmwit> | LBA? |
| 08:28:04 | <copumpkin> | linear bounded automaton |
| 08:28:34 | <copumpkin> | hrm |
| 08:28:42 | <dancor_> | ski: Traversable vs views? http://moonpatio.com:8080/fastcgi/hpaste.fcgi/view?id=2516#a2516 |
| 08:29:02 | <Twey> | « Hi Will be done within time and budget .............. If you have any query plz ask without any hesitation ....... Best Regards » |
| 08:29:05 | <Twey> | ACTION chuckles. |
| 08:29:30 | <WorkyBob> | shame someone pointed out the imposibility to them |
| 08:29:31 | <dancor_> | i think that if i had data Stmt expr = StmtBreak expr Other Stuff | .. then Traversable would be perfect |
| 08:29:59 | <dancor_> | but since i have data Stmt = StmtBreak Expr Other Stuff | .. i don't think i can use Traversable, is that correct? |
| 08:30:15 | <Twey> | « I will build the program that not only detect infinite loop as well as it will checked also improper if condition and also switch.Program also trying to read the logic of recursion and if it is improper then it will prompt the list of suggesstion.So I am confident to build your project in c# with Sql Sever.I would accept payment after you satishfied with the work. Regards Sumanta » |
| 08:30:28 | <Twey> | This is a real lesson in why not to use rent-a-coder sites |
| 08:30:32 | <copumpkin> | is that a real reasponse? |
| 08:30:33 | <copumpkin> | wow |
| 08:30:35 | <Twey> | Yeah |
| 08:30:49 | <WorkyBob> | >.< |
| 08:30:51 | <Twey> | (or C# programmers :-P) |
| 08:30:55 | <Ycros> | Twey: oh, I was reading that earlier, it was totally hilarious |
| 08:30:57 | <copumpkin> | he should've mentioned active directory, and used the word enterprise at least twice |
| 08:31:02 | <Twey> | Hahaha |
| 08:31:07 | <WorkyBob> | hahahahaha |
| 08:31:36 | <copumpkin> | :) |
| 08:31:40 | <WorkyBob> | he didn't mention XML either |
| 08:31:46 | <Twey> | Or Java |
| 08:31:47 | <ski> | dancor_ : have you seen mmorrow's `Cxt'/`View' ? |
| 08:31:48 | <WorkyBob> | surely XML would be needed to solve the halting problem |
| 08:31:51 | <Twey> | Or is Java no longer the In Thing? |
| 08:31:55 | <WorkyBob> | no, Java's old |
| 08:31:57 | <WorkyBob> | sorry |
| 08:32:00 | <Twey> | Damn |
| 08:32:04 | <WorkyBob> | you're obviously a bad programmer Twey |
| 08:32:07 | <WorkyBob> | not keeping up with the times |
| 08:32:34 | <ski> | dancor_ : btw, i'm doubtful of `class Look a b where look :: a -> View a b' to be that useful |
| 08:33:25 | <dancor_> | ski: i haven't where is mmorrow's stuff, #haskellogs? |
| 08:33:28 | <Twey> | I know, it's shocking |
| 08:33:57 | <ski> | mmorrow : well, <http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2486> at least .. possibly mmorrow can give better reference |
| 08:34:38 | <ski> | er |
| 08:34:48 | <ski> | s/mmorrow :/dancor_ :/ |
| 08:35:56 | <ski> | (dancor_ : e.g. see `accumView' there) |
| 08:37:52 | <dancor_> | hm |
| 08:38:14 | <dancor_> | it is true that Traversable isn't appropriate here right? |
| 08:38:18 | <dancor_> | it seems so close |
| 08:39:18 | <ski> | `Traversable' wants to work with a parameterized type |
| 08:39:35 | <dancor_> | ya |
| 08:39:36 | <dancor_> | ok |
| 08:39:39 | <ski> | you just want to work with "all substructures of type `Expr'" |
| 08:39:50 | <ski> | there might be some SYB you could use .. |
| 08:40:13 | <mmorrow> | dancor: here's a paste from a few days ago http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2486 |
| 08:40:23 | <ski> | you could of course write an `traverseExpr :: Applicative i => (Expr -> i Expr) -> (Stmt -> i Stmt)' yourself |
| 08:40:44 | <dancor_> | mmorrow: yes that's very interesting and your TH skills are way beyond me :) |
| 08:41:26 | <mmorrow> | dancor_: heh, what are you going for? |
| 08:41:57 | <dancor_> | well i will probably want to do this with other datatypes besides Stmt and Expr as well |
| 08:42:16 | <dancor_> | but maybe i'll just write traverseExpr for now then consider insane TH later |
| 08:42:36 | <dancor_> | mmorrow: i'm just trying to do abstract syntax tree manipulations |
| 08:43:48 | <mmorrow> | what i really want to be able to do is (and andyjgill's KURE pkg does this, but i haven't worked out how to generate all the instance, functions, etc code i need to be able to use it quite yet) is to be able to write a function that does some little/specific transformation to an AST, and then be able to apply that, with the choice of top-down or bottom-up, to an expression. and syb doesn't quite do it for me since i need to also thread a |
| 08:43:49 | <mmorrow> | monad through it. |
| 08:44:00 | <mmorrow> | dancor_: totally, me too |
| 08:44:07 | <dancor_> | hah nice |
| 08:44:21 | <ski> | Data.Generics.Schemes.everywhereM :: Monad m => (forall a. Data a => a -> m a) -> (forall a. Data a => a -> m a) |
| 08:44:36 | <mmorrow> | dancor_: (and all this is a product of being completely fed up with writing (essentially) the same traversals over each new AST) |
| 08:44:46 | <ski> | dancor_ : that's what i was thinking about |
| 08:45:21 | <mmorrow> | ski: yeah, the thing with everywhereM though is that you have no control over traversal strategy |
| 08:45:44 | <mmorrow> | (but everywhere(M) is totally handay, don't get me wrong) |
| 08:46:01 | <ski> | *nod* |
| 08:46:43 | <mmorrow> | hmm, i wonder ... you could find out what it's doing by using a state monad.. |
| 08:46:48 | <mmorrow> | > everywhereM |
| 08:46:50 | <lambdabot> | Overlapping instances for GHC.Show.Show |
| 08:46:50 | <lambdabot> | (Data.... |
| 08:47:55 | <ski> | ACTION wonders whether `everywhere' traverses into existentially hidden structures, having the `Data' constraints |
| 08:47:59 | <Gracenotes> | :t everywhereM |
| 08:48:01 | <lambdabot> | forall (m :: * -> *) a. (Data a, Monad m) => GenericM m -> a -> m a |
| 08:48:09 | <mmorrow> | > flip runState 0 (everywhereM (\_ -> do i <- get; put (i+1); return (i::Int)) (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]])) |
| 08:48:11 | <lambdabot> | Couldn't match expected type `a' |
| 08:48:26 | <mmorrow> | oh, what is the monadic mkT? |
| 08:48:59 | <mmorrow> | > flip runState 0 (everywhereM (mkM (\_ -> do i <- get; put (i+1); return (i::Int))) (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]])) |
| 08:49:01 | <lambdabot> | (Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {... |
| 08:49:19 | <mmorrow> | > levels (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]])) |
| 08:49:20 | <lambdabot> | <no location info>: parse error on input `)' |
| 08:49:23 | <mmorrow> | > levels (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]]) |
| 08:49:24 | <lambdabot> | [[0],[1,3],[2,4]] |
| 08:49:30 | <mmorrow> | > levels $ flip runState 0 (everywhereM (mkM (\_ -> do i <- get; put (i+1); return (i::Int))) (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]])) |
| 08:49:31 | <lambdabot> | Couldn't match expected type `Data.Tree.Tree a' |
| 08:50:01 | <ski> | @type levels |
| 08:50:02 | <lambdabot> | forall a. Tree a -> [[a]] |
| 08:50:06 | <re__> | hi there |
| 08:50:19 | <re__> | anyone there who likes to help me a little with profiling? |
| 08:50:33 | <mmorrow> | > levels $ flip evalState 0 (everywhereM (mkM (\_ -> do i <- get; put (i+1); return (i::Int))) (Node 0 [Node 1 [Node 2 []], Node 3 [Node 4 []]])) |
| 08:50:34 | <lambdabot> | [[0],[1,3],[2,4]] |
| 08:50:50 | <mmorrow> | so i guess it's depth-first |
| 08:50:56 | <mmorrow> | err |
| 08:51:04 | <mmorrow> | yeah |
| 08:51:15 | <mmorrow> | no |
| 08:51:28 | <mmorrow> | breadth-first |
| 08:51:46 | <mmorrow> | top-down |
| 08:53:59 | <JaffaCake> | mmorrow: have you tried using StableName for vacuum, instead of unsafePtrEquality? |
| 08:54:51 | <mmorrow> | dancor_: anyways, the code to generate those instances of View was semi-epic... you have to build the graph of all reachable types from a type, compute the SCC that that type's in, build a Map of Type -> [(Int{-con tag-},[(Int{-field index-}, Type)]], and finally generate the View instance picking out the 'b' in (View a b) from all the places in 'a' where it occurs |
| 08:55:32 | <mmorrow> | JaffaCake: i haven't. do you think it would be a lot of overhead for a graph of, say, 1000+ nodes? |
| 08:55:58 | <JaffaCake> | well, using ptr equality is quadratic, whereas with StableName you could have a hash table |
| 08:56:20 | <mmorrow> | ahhh, yeah true. i have to do linear search through seen nodes with ptr equality.. |
| 08:56:25 | <JaffaCake> | there might be a constant factor, but I think you'd win with large graphs |
| 08:56:52 | <mmorrow> | hmm, interesting. i'll try it out. |
| 08:57:24 | <mmorrow> | JaffaCake: what about the possibility of false negatives? |
| 08:57:52 | <JaffaCake> | I don't think it's any worse than with ptr equality |
| 08:58:04 | <mmorrow> | nice |
| 08:59:07 | <ski> | @hoogle GenParser t s [t] -> GenParser t s () |
| 08:59:08 | <lambdabot> | No results found |
| 08:59:43 | <dancor_> | mmorrow: sorry i was playing with the tree example. it's depth-first right, since the numbering is the same |
| 08:59:44 | <ski> | @hoogle GenParser t s [t] -> GenParser t s a -> GenParser t s a |
| 08:59:45 | <lambdabot> | No results found |
| 09:00:02 | <ski> | > levels $ flip evalState 0 (everywhereM (mkM (\_ -> do i <- get; put (i+1); return (i::Int))) (Node 0 [fix $ \t -> Node 1 [Node 2 [t]], Node 3 [Node 4 []]])) |
| 09:00:03 | <lambdabot> | [[0],[1,3],[2,4],[1],[2],[1],[2],[1],[2],[1],[2],[1],[2],[1],[2],[1],[2],[1... |
| 09:00:29 | <mmorrow> | dancor: ah yeah, depth-first (i confused myself) |
| 09:00:51 | <dancor_> | mmorrow: and, about TH, it all seems very epic to me :) |
| 09:01:58 | <mmorrow> | dancor_: heh. once you get a code-base of it though, it starts to get self-supporting in that you can use it to generate more of it to use it to ... |
| 09:02:24 | <dancor_> | you don't change TH. it changes you (and itself) |
| 09:03:16 | <mmorrow> | for instance, once i finally figure out howtf to generate the KURE support code for the TH AST itself, then i can use kure to manipulate the TH which'll then generate the kure support code for other ast's more easily.. |
| 09:03:30 | <mmorrow> | dancor_: totally |
| 09:05:40 | <mmorrow> | well, kure is more for transforming an ast than it is for building expression/whatever with that ast, but you know what i mean :) |
| 09:06:00 | <dancor_> | i'm reading about kure now |
| 09:06:52 | <mmorrow> | dancor_: it's interesting. the trickyness comes in when your ast's cons have fields like: |
| 09:07:18 | <mmorrow> | data Exp = ... | Foo [Exp] (Maybe Exp) ([Stmt],Maybe ..) | .... |
| 09:07:39 | <mmorrow> | then you have to figure out how to see through/something the []s and Maybes |
| 09:08:03 | <mmorrow> | (and (,,...,)s) |
| 09:08:13 | <mmorrow> | which is a total pita |
| 09:09:59 | <quicksilver> | is implementing Num to lift things into your EDSL *actually* a sensible technique |
| 09:10:08 | <quicksilver> | or is it in fact a rather despicable hack? |
| 09:10:43 | <mmorrow> | heh, it'd be nice if there was a class with only fromInteger.. |
| 09:11:13 | <mmorrow> | because i feel like whenever i make Num instances, at least abs and signum are error "..." |
| 09:11:27 | <quicksilver> | ACTION nods |
| 09:11:34 | <quicksilver> | well I was looking at the cafe thread about bool as a type class. |
| 09:11:45 | <quicksilver> | but to me, it's always felt like rather an abuse to do this at all. |
| 09:11:49 | <quicksilver> | ACTION shrugs |
| 09:12:04 | <lars9> | how to understand fmap vs. map? |
| 09:12:12 | <quicksilver> | map only works on lists |
| 09:12:20 | <quicksilver> | fmap works on all functors (including lists) |
| 09:12:41 | <mmorrow> | @src [] fmap |
| 09:12:42 | <lambdabot> | fmap = map |
| 09:12:48 | <mmorrow> | @src [] Maybe |
| 09:12:48 | <lambdabot> | Source not found. Just what do you think you're doing Dave? |
| 09:12:54 | <mmorrow> | > fmap (*2) (Just 4) |
| 09:12:55 | <lambdabot> | Just 8 |
| 09:13:09 | <dancor_> | @src Maybe fmap |
| 09:13:09 | <lambdabot> | fmap _ Nothing = Nothing |
| 09:13:09 | <lambdabot> | fmap f (Just a) = Just (f a) |
| 09:13:15 | <mmorrow> | heh, oops |
| 09:13:30 | <dancor_> | allyoops |
| 09:13:33 | <lars9> | >fmap (*2) [1,2,3] |
| 09:13:42 | <lars9> | > fmap (*2) [1,2,3] |
| 09:13:43 | <lambdabot> | [2,4,6] |
| 09:13:57 | <lars9> | > fmap (*2) (*3) |
| 09:13:58 | <lambdabot> | Overlapping instances for GHC.Show.Show (a -> a) |
| 09:13:58 | <lambdabot> | arising from a use of `... |
| 09:14:09 | <mmorrow> | > (fmap . fmap . fmap) (*2) [Just [4]] |
| 09:14:10 | <lambdabot> | [Just [8]] |
| 09:14:13 | <WorkyBob> | > fmap (*2) (*3) $ 6 |
| 09:14:14 | <lambdabot> | 36 |
| 09:14:27 | <WorkyBob> | > fmap fmap fmap fmap fmap (*2) [Just [4]] |
| 09:14:29 | <lambdabot> | Couldn't match expected type `a -> a1' against inferred type `[a2]' |
| 09:14:34 | <WorkyBob> | damn, need parens for that one |
| 09:14:44 | <lars9> | > (fmap (*2) (*3)) 4 |
| 09:14:44 | <WorkyBob> | > fmap (fmap fmap fmap) fmap (*2) [Just [4]] |
| 09:14:45 | <lambdabot> | 24 |
| 09:14:46 | <lambdabot> | [Just [8]] |
| 09:15:17 | <lars9> | hey, is fmap (*2) (*3) equal to (*6) ? |
| 09:15:22 | <WorkyBob> | yes |
| 09:15:31 | <WorkyBob> | fmap (*2) (*3) is (*2) . (*3) |
| 09:15:41 | <Axman6> | hmm, this seems wrong to me, but i can't think of a situation that disproves it. are powers of 2 only dividible by smaller powers of 2? |
| 09:15:53 | <WorkyBob> | Axman6: yes |
| 09:15:57 | <WorkyBob> | and it's easily proved |
| 09:16:01 | <Axman6> | @src (->) fmap |
| 09:16:01 | <lambdabot> | fmap = (.) |
| 09:16:05 | <WorkyBob> | break them down to prime factors |
| 09:16:15 | <WorkyBob> | 2, 2, 2, 2, 2..... 2, 2 |
| 09:16:16 | <Axman6> | and all you get is 2's |
| 09:16:18 | <qebab> | Axman6: Prime factorisation of a power of 2 consists only of 2s. |
| 09:16:27 | <lars9> | what does this command mean? @src |
| 09:16:37 | <WorkyBob> | lars9: it displays the source for a function |
| 09:16:45 | <Axman6> | @src map |
| 09:16:45 | <lambdabot> | map _ [] = [] |
| 09:16:45 | <lambdabot> | map f (x:xs) = f x : map f xs |
| 09:16:46 | <WorkyBob> | as defined by the haskell report IIRC |
| 09:17:30 | <lars9> | @src fmap (*2) (+3) |
| 09:17:31 | <lambdabot> | Source not found. I can't hear you -- I'm using the scrambler. |
| 09:17:46 | <lars9> | @src (fmap (*2) (+3)) |
| 09:17:46 | <lambdabot> | Source not found. Are you on drugs? |
| 09:17:55 | <WorkyBob> | you can't ask for the source for an expresison |
| 09:17:57 | <WorkyBob> | only for a function |
| 09:18:04 | <Axman6> | lars9: only things in the haskell report (and possibly some others) are in @src |
| 09:18:07 | <ski> | Axman6 : `2' is a power of `2', `2' divides `2', `2' is not smaller than `2' |
| 09:18:08 | <WorkyBob> | what Axman6 did was ask for the source of fmap |
| 09:18:08 | <lars9> | @src fmap |
| 09:18:09 | <lambdabot> | Source not found. I can't hear you -- I'm using the scrambler. |
| 09:18:09 | <Axman6> | @src Maybe |
| 09:18:09 | <lambdabot> | data Maybe a = Nothing | Just a |
| 09:18:11 | <WorkyBob> | and a specific fmap |
| 09:18:19 | <WorkyBob> | the fmap for the type (->) |
| 09:18:23 | <WorkyBob> | i.e. for functions |
| 09:18:27 | <WorkyBob> | @src (->) fmap |
| 09:18:27 | <lambdabot> | fmap = (.) |
| 09:18:56 | <Axman6> | ski: yeah, that's true. |
| 09:19:25 | <ski> | @src [] mzero |
| 09:19:25 | <lambdabot> | mzero = [] |
| 09:19:43 | <ski> | (`[]' is not a function) |
| 09:19:45 | <quicksilver> | Axman6: the fundamental theorem of arithmetic explains why/how you can generate all factors from the prime factorisation. |
| 09:19:49 | <lars9> | @src forM |
| 09:19:50 | <lambdabot> | forM = flip mapM |
| 09:20:01 | <WorkyBob> | bah |
| 09:20:05 | <WorkyBob> | @src mapM |
| 09:20:06 | <lambdabot> | mapM f as = sequence (map f as) |
| 09:20:12 | <WorkyBob> | fmap fmap fmap sequence fmap is way better |
| 09:20:13 | <WorkyBob> | :( |
| 09:21:01 | <lars9> | ive still not got used to xxxM functions, often confused by them... |
| 09:21:29 | <WorkyBob> | what do you find confusing about them specifically? |
| 09:21:39 | <WorkyBob> | and do you understand the functor and applicative functions? |
| 09:22:06 | <WorkyBob> | (is guessing not, because most of the xxxM functions are actually applicative ones) |
| 09:22:43 | <lars9> | e.g. liftM, it converts a (a -> a) to (a -> m a) ? |
| 09:22:51 | <quicksilver> | :t liftM |
| 09:22:52 | <lambdabot> | forall a1 r (m :: * -> *). (Monad m) => (a1 -> r) -> m a1 -> m r |
| 09:22:54 | <WorkyBob> | liftM is also known as fmap |
| 09:23:05 | <quicksilver> | ^^ no, it converts an (a -> a) to a (m a -> m a) |
| 09:23:07 | <quicksilver> | or more generally |
| 09:23:13 | <WorkyBob> | it converts an (a -> b) to a (m a -> m b) |
| 09:23:14 | <quicksilver> | it converts an (a -> b) to a (m a -> m b) |
| 09:23:19 | <WorkyBob> | jnix! |
| 09:23:20 | <WorkyBob> | :D |
| 09:23:53 | <lars9> | so, liftM (*2) can twice all items in a list? |
| 09:24:01 | <WorkyBob> | indeed |
| 09:24:10 | <WorkyBob> | but in general, calling it fmap is better style |
| 09:24:18 | <lars9> | i see. |
| 09:24:20 | <WorkyBob> | or calling it (<$>) if you want to use it infix |
| 09:24:31 | <WorkyBob> | > (*2) <$> [1,2,3] |
| 09:24:33 | <lambdabot> | [2,4,6] |
| 09:25:24 | <lars9> | and 'return' converts a -> m a? |
| 09:25:38 | <lars9> | :t return |
| 09:25:39 | <lambdabot> | forall a (m :: * -> *). (Monad m) => a -> m a |
| 09:25:48 | <WorkyBob> | yes, but it should really be called pure |
| 09:25:58 | <lars9> | :t pure |
| 09:25:59 | <lambdabot> | forall a (f :: * -> *). (Applicative f) => a -> f a |
| 09:26:11 | <lars9> | @src pure |
| 09:26:11 | <lambdabot> | Source not found. Just what do you think you're doing Dave? |
| 09:26:17 | <WorkyBob> | @src [] pure |
| 09:26:18 | <lambdabot> | pure = return |
| 09:26:19 | <Gracenotes> | return makes some sense for IO |
| 09:26:30 | <WorkyBob> | yeh, return makes sense as a synonym |
| 09:26:34 | <Gracenotes> | like sequence and forever |
| 09:26:36 | <WorkyBob> | in a lot of cases |
| 09:26:49 | <WorkyBob> | heh, but sequence is an applicative function |
| 09:27:16 | <lars9> | multiple notations on one function ... is sometimes confusing too |
| 09:27:20 | <Gracenotes> | monadic naming seems to be influenced by IO and effectful ordering in that context |
| 09:27:21 | <WorkyBob> | yep |
| 09:27:32 | <WorkyBob> | lars9: it's because monads were discovered to be useful early on |
| 09:27:43 | <WorkyBob> | but the more general classes higher up the tree only later |
| 09:28:11 | <lars9> | i dunno Applicative yet, need more reading on it. |
| 09:28:15 | <WorkyBob> | lars9: http://noordering.wordpress.com/2009/03/31/how-you-shouldnt-use-monad/ <-- try this as another take on monads^H^H^H^H^H^H the tree that builds up to monads |
| 09:29:00 | <lars9> | :t forM |
| 09:29:01 | <lambdabot> | forall a (m :: * -> *) b. (Monad m) => [a] -> (a -> m b) -> m [b] |
| 09:29:49 | <lars9> | :t zipWithM_ |
| 09:29:51 | <lambdabot> | forall a b (m :: * -> *) c. (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m () |
| 09:30:09 | <lars9> | :t mapM |
| 09:30:10 | <lambdabot> | forall a (m :: * -> *) b. (Monad m) => (a -> m b) -> [a] -> m [b] |
| 09:30:16 | <WorkyBob> | all 3 of those should be in applicative |
| 09:30:17 | <WorkyBob> | not monad |
| 09:30:45 | <lars9> | is forM x y = mapM y x? |
| 09:30:49 | <WorkyBob> | yes |
| 09:30:56 | <Axman6> | @src forM |
| 09:30:57 | <lambdabot> | forM = flip mapM |
| 09:31:01 | <Axman6> | @src flip |
| 09:31:01 | <lambdabot> | flip f x y = f y x |
| 09:31:12 | <WorkyBob> | some people like to write in the style of for x in [1,3,5,6,7] do this stuff |
| 09:31:14 | <Gracenotes> | totally yessssssss dude |
| 09:31:15 | <Axman6> | > flip f x y |
| 09:31:16 | <lambdabot> | Add a type signature |
| 09:31:20 | <Axman6> | > flip f x y :: Expr |
| 09:31:22 | <lambdabot> | f y x |
| 09:32:05 | <Gracenotes> | > forM [1,2,3] (replicate 2) |
| 09:32:07 | <lambdabot> | [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]] |
| 09:32:20 | <lars9> | i do prefer python's 'there is only one way for one thing' way... more friendly to newbies |
| 09:32:23 | <lars9> | :D |
| 09:32:34 | <quicksilver> | but it's not actually true. |
| 09:32:38 | <Axman6> | but there isn't only one way to do things |
| 09:32:46 | <quicksilver> | all languages have multiple ways to do things |
| 09:33:04 | <Gracenotes> | lars9: that's the Python commuity's way of forcing idiomatic behavior in a hodge-podge language :P |
| 09:33:13 | <dancor_> | well, there is more consensus in python |
| 09:33:19 | <dancor_> | ya |
| 09:33:25 | <Gracenotes> | the "pythonic" epithet ;) |
| 09:34:06 | <WorkyBob> | I'm not sure there is more consensus in python |
| 09:34:09 | <ski> | @type replicateM |
| 09:34:11 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => Int -> m a -> m [a] |
| 09:34:23 | <WorkyBob> | there's more consensus about how to write things that don't tend to trip over runtime type checking |
| 09:34:28 | <WorkyBob> | but that's not a problem we hit |
| 09:34:40 | <lars9> | if i have a function a -> b, but i want a -> m b, i should just use pure f? |
| 09:34:44 | <dancor_> | i do prefer qualified imports |
| 09:34:47 | <WorkyBob> | lars9: no |
| 09:34:48 | <eivuokko> | The scope is usually different. The python "one-way" usually refers to expression/statement level, and there are very strong idioms at that level. Haskell has only few idioms at that level. (Function composition in few forms, really.) |
| 09:34:53 | <WorkyBob> | pure f would give you m (a -> b) |
| 09:35:02 | <ski> | lars9 : `pure . f' |
| 09:35:08 | <WorkyBob> | or fmap pure f |
| 09:35:17 | <WorkyBob> | or pure <$> f |
| 09:35:18 | <Gracenotes> | useless use of fmap! >_> |
| 09:35:21 | <lars9> | :t (pure . length) |
| 09:35:22 | <lambdabot> | forall (f :: * -> *) a. (Applicative f) => [a] -> f Int |
| 09:35:26 | <WorkyBob> | Gracenotes: so true |
| 09:35:30 | <Gracenotes> | :P |
| 09:35:45 | <lars9> | :t pure <$> length |
| 09:35:46 | <lambdabot> | forall (f :: * -> *) a. (Applicative f) => [a] -> f Int |
| 09:35:52 | <lars9> | :t pure $ length |
| 09:35:53 | <lambdabot> | forall (f :: * -> *) a. (Applicative f) => f ([a] -> Int) |
| 09:36:00 | <WorkyBob> | :t return `liftM` length |
| 09:36:01 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => [a] -> m Int |
| 09:36:55 | <lars9> | :t (.) |
| 09:36:56 | <lambdabot> | forall b c a. (b -> c) -> (a -> b) -> a -> c |
| 09:37:05 | <Axman6> | > pure <$> length [1..10] :: Maybe Int |
| 09:37:06 | <lambdabot> | Couldn't match expected type `GHC.Types.Int' |
| 09:37:08 | <lars9> | :t ($) |
| 09:37:08 | <lambdabot> | forall a b. (a -> b) -> a -> b |
| 09:37:21 | <ski> | @type mapAndUnzipM |
| 09:37:22 | <lambdabot> | forall a (m :: * -> *) b c. (Monad m) => (a -> m (b, c)) -> [a] -> m ([b], [c]) |
| 09:37:40 | <quicksilver> | I hate the way that error message exposes something implementation dependent where the type was defined. |
| 09:37:48 | <copumpkin> | that's a pretty intense function |
| 09:37:56 | <Gracenotes> | > (pure <$> length) [1..10] :: Maybe Int |
| 09:37:57 | <lambdabot> | Just 10 |
| 09:38:22 | <ski> | (quicksilver : .. seconded) |
| 09:38:33 | <Axman6> | oh right, bount the list to length |
| 09:39:24 | <quicksilver> | ski: the standard should mandate certain things about error messages. E.g. "In error messages built in types like Int may be referred to as Prelude.Int or Int, but by no other names" |
| 09:39:29 | <Gracenotes> | speaking about useless uses of cat, echo "hello" | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat |
| 09:39:56 | <Gracenotes> | ACTION wonders how long that can go on |
| 09:41:44 | <copumpkin> | until you run out of FDs? |
| 09:42:08 | <lars9> | what kind of projects do you use haskell on? |
| 09:42:13 | <dancor_> | or bash 65k char limit? |
| 09:42:21 | <copumpkin> | lars9: I do porn administration |
| 09:42:56 | <dancor_> | does that make use of Set |
| 09:42:59 | <Gracenotes> | I ray trace .. images of pumpkin doing porn administration. |
| 09:43:05 | <shapr> | copumpkin: wtf? |
| 09:43:10 | <copumpkin> | ACTION whistles |
| 09:43:28 | <dancor_> | i'm just glad that copumpkin is being safe |
| 09:43:34 | <shapr> | Gee, I've used Haskell to index and sort mailing lists, hack on irc bots, get paid hack on webservers, and lots more. |
| 09:43:34 | <copumpkin> | :) |
| 09:43:44 | <ski> | echo "hello" | fix (cat |) |
| 09:43:49 | <Gracenotes> | really though, I've made hash rainbow tables, a ray tracer, working on IRC bot, regexen... |
| 09:43:50 | <shapr> | porn may be free of side-effects, but it's also very lonely. |
| 09:43:57 | <ivanm> | shapr: you use haskell to hack on webservers? |
| 09:44:03 | <ivanm> | so you write haskell code that writes code? |
| 09:44:03 | <ivanm> | ;-) |
| 09:44:07 | <shapr> | ivanm: Well, I got paid to work on HAppS for a year. |
| 09:44:17 | <ivanm> | it's just the way you said it ;-) |
| 09:44:28 | <shapr> | ivanm: And yes, pesco and I had a QuickCheckM instance that fuzzed http at one point years ago. |
| 09:44:35 | <ivanm> | heh |
| 09:44:37 | <shapr> | But John Hughes beat us to the punch with quviq, so we gave it up. |
| 09:44:46 | <ivanm> | quviq? never heard of it |
| 09:44:51 | <ivanm> | and what do you mean by "fuzzed"? |
| 09:44:59 | <shapr> | @go protocol fuzzing |
| 09:45:00 | <lambdabot> | http://en.wikipedia.org/wiki/Fuzz_testing |
| 09:45:19 | <ivanm> | ahhhhh |
| 09:45:27 | <lars9> | :t zipWithM_ |
| 09:45:28 | <Gracenotes> | garbage in, garbage out, huh |
| 09:45:28 | <lambdabot> | forall a b (m :: * -> *) c. (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m () |
| 09:45:40 | <shapr> | I wonder if I still have the code for that lying around, that would be fun to resurrect. |
| 09:45:57 | <lars9> | :t zipWithM |
| 09:45:58 | <lambdabot> | forall a b (m :: * -> *) c. (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c] |
| 09:46:06 | <quicksilver> | a random thread interleave tester would be a very good tool for GHC.Conc testing. |
| 09:46:44 | <lars9> | i can understand m [c], it's a monad containing a list of c, but what is m ()? |
| 09:46:48 | <lars9> | :t () |
| 09:46:49 | <lambdabot> | () |
| 09:47:02 | <lars9> | :t m () |
| 09:47:03 | <lambdabot> | Couldn't match expected type `() -> t' against inferred type `Expr' |
| 09:47:03 | <lambdabot> | In the expression: m () |
| 09:47:13 | <Gracenotes> | lars9: "m ()" is used when the result of the monad computation doesn't matter as much as the effects from it |
| 09:47:16 | <Gracenotes> | generally |
| 09:47:27 | <Gracenotes> | for example, print is IO () |
| 09:47:29 | <shapr> | How else could you do a void return in Haskell? |
| 09:47:47 | <ski> | lars9 : s/it's a monad containing/it's a monadic action returning/ |
| 09:47:56 | <eivuokko> | lars9, () is called unit type, you can think of it as data () = () (not valid syntax). It usually means "don't care" when you need concrete type (not type variable) |
| 09:48:06 | <shapr> | hei eivuokko! long time no see. |
| 09:49:12 | <eivuokko> | shapr, Hello. Yes, been away. How are you? |
| 09:49:44 | <shapr> | Busy writing C#, how's life with you? |
| 09:49:47 | <Gracenotes> | boolean is True | False... it's binary. Unit is unary: not two values, but one... |
| 09:50:01 | <copumpkin> | or two |
| 09:50:12 | <copumpkin> | or a hunded |
| 09:50:15 | <Gracenotes> | no bottoms for you |
| 09:50:18 | <eivuokko> | shapr, tried F# ? :) I've been playing it with lately. Although it's kinda horrible...wtb haskell for .net ;) |
| 09:50:23 | <copumpkin> | *hundred even |
| 09:50:49 | <Axman6> | Gracenotes: :( |
| 09:50:59 | <copumpkin> | Gracenotes: do you like bottom? |
| 09:51:23 | <Gracenotes> | well. you can catch most of them in the IO monad |
| 09:51:42 | <lars9> | :t _|_ |
| 09:51:43 | <lambdabot> | parse error on input `|' |
| 09:51:55 | <lars9> | m(_ _)m |
| 09:52:13 | <hatds> | ?instances MonadIO |
| 09:52:14 | <lambdabot> | ContT r m, ErrorT e m, IO, RWST r w s m, ReaderT r m, StateT s m, WriterT w m |
| 09:52:22 | <Axman6> | it always annoyed me that _|_ isn;t actually haskell |
| 09:52:23 | <Gracenotes> | > let ~ (_,_) = undefined in 0.0 |
| 09:52:25 | <lambdabot> | 0.0 |
| 09:52:35 | <shapr> | eivuokko: I haven't tried F#, everytime I get the urge to do something fun with .NET I have SharePoint flashbacks and buy more hardware instead. |
| 09:52:49 | <Axman6> | haha |
| 09:52:54 | <Gracenotes> | actually, ~ is implicit but anyways |
| 09:53:14 | <Axman6> | @quote shapr I haven't tried F#, everytime I get the urge to do something fun with .NET I have SharePoint flashbacks and buy more hardware instead. |
| 09:53:15 | <lambdabot> | No quotes match. |
| 09:53:22 | <Axman6> | @remember shapr I haven't tried F#, everytime I get the urge to do something fun with .NET I have SharePoint flashbacks and buy more hardware instead. |
| 09:53:23 | <lambdabot> | Okay. |
| 09:53:25 | <Axman6> | even |
| 09:53:38 | <shapr> | At this point I have enough hardware that I could actually run a usable SharePoint server. Specifically, I have an eight core Xeon with 16gb of ram. |
| 09:53:46 | <eivuokko> | shapr, Heh. -.-' |
| 09:53:50 | <lars9> | i wonder what haskell looks like in the eyes of someone who learn haskell as his/her 1st programming language. |
| 09:54:14 | <shapr> | lars9: I find it more interesting to hear about what C looks like to someone who learns Haskell as his/her first language. |
| 09:54:21 | <Axman6> | lars9: hopefully pretty nice |
| 09:54:37 | <Axman6> | shapr: i could go find some and ask them |
| 09:54:43 | <shapr> | lars9: I heard that there were a few student at Chalmers who had exactly that experience. |
| 09:54:48 | <lars9> | maybe as easy as we see C |
| 09:55:16 | <shapr> | I think it was either Anders or Björn who said that they had lots of trouble understanding C until someone told them that every function was in IO. |
| 09:55:30 | <eivuokko> | lars9, With somewhat right background, haskell's pretty intuitive. |
| 09:56:41 | <quicksilver> | shapr: that sounds a little too like what someone would say they thought because they knew other people wanted to hear it :) |
| 09:56:44 | <Axman6> | ACTION likes writing referencially transparent C functions |
| 09:56:46 | <quicksilver> | shapr: if it's true, though :) |
| 09:57:10 | <shapr> | quicksilver: I don't know, I haven't spoken to anyone myself who had learned Haskell first. |
| 09:57:13 | <Gracenotes> | Axman6: but how do you prove it??????? *wags eyebrows* |
| 09:57:21 | <Axman6> | hmm, i thought i'd just written one, but it may not be, considering it will be have differently on differing hardware |
| 09:57:22 | <mux> | ACTION likes to use __attribute__((pure)) |
| 09:57:24 | <lars9> | i guess so, but i have no chance to experience that anymore. I'm already used to break down a problem into C code pieces. and found it's hard to think in the haskell's pure functional way. |
| 09:57:42 | <Axman6> | mux: is that a real thing? |
| 09:57:49 | <mux> | Axman6: GCC extension |
| 09:57:50 | <eivuokko> | It's a gcc thing. |
| 09:57:58 | <quicksilver> | mux: I like __attribute__((can_you_believe_how_ugly_this_syntax_is)) |
| 09:57:59 | <Axman6> | good enough for me. what's it do? |
| 09:58:03 | <mux> | quicksilver: :-) |
| 09:58:04 | <Gracenotes> | Axman6: well. I'd like to think of referential transparency within a runtime. not from runtime instance to runtime instance. |
| 09:58:09 | <mux> | Axman6: tells the compiler your function is pure |
| 09:58:12 | <quicksilver> | Axman6: gives the optimiser a hint. |
| 09:58:22 | <Axman6> | and how do you use it? |
| 09:58:24 | <mux> | except that there are pure and pure2 attributes with subtle differences but you get the idea |
| 09:58:32 | <Axman6> | ACTION wants to show off to his lecturer is his current comp course |
| 09:58:32 | <quicksilver> | Axman6: it can for example CSE expressions using that function |
| 09:58:40 | <quicksilver> | Axman6: just like it can (already) CSE + and * |
| 09:58:46 | <quicksilver> | because it already knows + and * are pure. |
| 09:58:47 | <Axman6> | bah, i do CSE myself :P |
| 09:59:06 | <mux> | Axman6: you add that __attribute__((pure)) stuff at the end of your function prototype |
| 09:59:07 | <ski> | (Gracenotes : how about code mobility ? image save & restore ?) |
| 09:59:15 | <Axman6> | ok, thanks :) |
| 09:59:27 | <quicksilver> | as the optimiser gets better, opportunities for CSE may appear which aren't immediately obvious on inspection of the input source |
| 09:59:30 | <mux> | oh, it seems pure2 is now named 'const' |
| 09:59:30 | <Gracenotes> | ski: well. Then I guess it's part of the same runtime, in the context of that code. |
| 09:59:48 | <mux> | what a bad naming |
| 10:00:35 | <Gracenotes> | hmmm |
| 10:00:43 | <mornfall> | quicksilver: I think it's that ugly so there's no risk of conflict with any sensible future standard. ;) |
| 10:01:01 | <mux> | the 'const' attribute should be named 'pure', but I don't know how 'pure' should be named then |
| 10:02:30 | <Axman6> | quicksilver: the thing we're doing at the moment involves speeding up a fucntion by checking for powers of 2 and replacing multiplies and modulus' with <<, >> and & |
| 10:02:53 | <Axman6> | my version runs about 80% faster than the original :) |
| 10:03:26 | <Axman6> | j = j/k + (j%(k))*(n/k); --> j = (j >> powk) + ((j & mask) << nkpow); |
| 10:03:26 | <lars9> | im learning xmobar's source code. could anybody help me on some problems? http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5372#a5372 |
| 10:03:55 | <mux> | yay, STM code |
| 10:03:57 | <Neut> | http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2519#a2519 |
| 10:04:06 | <Neut> | what is wrong with my list comprehension in that code? |
| 10:04:10 | <Axman6> | g'day Neut |
| 10:04:11 | <mux> | lars9: what are the problems? |
| 10:04:21 | <Neut> | I get a non-exhaustive pattern error :/ |
| 10:04:24 | <Neut> | hey Axman |
| 10:04:31 | <Axman6> | Neut: were you in the 1100 lecture today? |
| 10:04:35 | <Neut> | good to see you |
| 10:04:37 | <Neut> | sure was, |
| 10:04:41 | <Neut> | were you? |
| 10:04:42 | <lars9> | here is the code http://tinyurl.com/npu66q |
| 10:04:51 | <shapr> | I wasn't! |
| 10:05:00 | <Axman6> | yep :) |
| 10:05:04 | <mux> | Neut: your healthPeople function takes a PeopleStats parameters, which is a list of triples |
| 10:05:11 | <Axman6> | man, clem's so awesome |
| 10:05:16 | <Neut> | why were you there lol? |
| 10:05:19 | <mux> | Neut: yet you only define healthyPeople for the case where your list contains only one element |
| 10:05:23 | <Axman6> | funsies :P |
| 10:05:35 | <mux> | Neut: foo [x] = ... means you're matching the case where you get a list with exactly one element |
| 10:05:45 | <Axman6> | heard there were baloons, and a friend of mine hasn't ever been to a clem lecture |
| 10:06:32 | <Neut> | mux: how do I modify it so that isnt the case? |
| 10:06:47 | <Neut> | Axman6: yeah he is good fun xD |
| 10:07:31 | <mux> | Neut: healthyPeople peoples = [ name | (name,height,weight) <- peoples, healthy height weight ] |
| 10:07:38 | <Axman6> | Neut: i think the function you want is: healthyPeople people = [(name, height, weight) | (name, height, weight) <- names, healthy height weight] |
| 10:07:51 | <mux> | Neut: note the == True is redundant in your list compreension |
| 10:07:52 | <Axman6> | uh, s/names/people |
| 10:08:03 | <mux> | Axman6: no, he only wants to return the names of the persons |
| 10:08:06 | <Teggy> | G'day all. |
| 10:08:08 | <Neut> | why is that mux? |
| 10:08:11 | <Axman6> | ah ok |
| 10:08:32 | <Axman6> | @check \x -> (x == True) == x |
| 10:08:33 | <lambdabot> | "OK, passed 500 tests." |
| 10:08:45 | <mux> | Neut: because the healthy function already returns boolean |
| 10:08:47 | <Axman6> | G'day Teggy |
| 10:08:50 | <Neut> | oh of course |
| 10:08:54 | <Neut> | thanks alot |
| 10:09:02 | <mux> | you're welcome |
| 10:09:27 | <Neut> | say Axman6, if your in the exam hall next week and wana put my ID on your paper that would be fine too |
| 10:09:29 | <Neut> | xD |
| 10:09:46 | <mux> | > 70/(1.83^2) |
| 10:09:46 | <Axman6> | mux: when i was taking the course Neut is now, i used to see if blah then True else False all the time |
| 10:09:48 | <lambdabot> | 20.902385858042937 |
| 10:09:52 | <mux> | yay, I'm healthy. |
| 10:10:00 | <mux> | Axman6: heh :-) |
| 10:10:12 | <Axman6> | > 90/(1.9^2) |
| 10:10:13 | <lambdabot> | 24.930747922437675 |
| 10:10:16 | <Axman6> | :( |
| 10:10:20 | <Axman6> | only just |
| 10:10:26 | <mux> | Axman6: nearly not healthy ;-) |
| 10:10:33 | <Axman6> | bmi's not a great measure though |
| 10:10:35 | <Neut> | *Argh*, I updated my kernal today and my computer is fail slow :( |
| 10:10:37 | <mux> | ACTION nods |
| 10:10:56 | <Axman6> | i mean, i'm a bit tubby, but not exactly fat |
| 10:12:10 | <Neut> | Axman6: we are pushed away from using ifs for some reason |
| 10:12:19 | <Axman6> | good |
| 10:12:22 | <mux> | because ifs are unaesthetic |
| 10:12:28 | <Axman6> | they're often misused |
| 10:12:48 | <Axman6> | they have their place, but there's often better waysx |
| 10:12:49 | <mux> | I always try to have pattern guards instead of ifs if possible |
| 10:13:10 | <Axman6> | i'll use if if the alternative is a case statement |
| 10:13:24 | <Neut> | epic, I have to use Kate because emacs lags too hard.. what an update *cries* |
| 10:13:40 | <Axman6> | tried vim? |
| 10:13:45 | <Axman6> | (or... a good OS?) |
| 10:13:46 | <Axman6> | >_> |
| 10:13:55 | <Neut> | what do you use? |
| 10:14:06 | <WorkyBob> | SubEthaEdit |
| 10:14:09 | <Axman6> | OS X |
| 10:14:19 | <Neut> | bleh not a mac fan |
| 10:14:29 | <WorkyBob> | what do you use? |
| 10:14:38 | <Neut> | ubuntu |
| 10:14:40 | <Axman6> | Clem's got one, so's Ben L, and all the other awesome people :P |
| 10:14:45 | <WorkyBob> | oh, no reason not to use a mac then |
| 10:14:46 | <Neut> | hahaha |
| 10:15:02 | <WorkyBob> | just a unix box... just happens to also run more apps |
| 10:15:30 | <Axman6> | Neut: the reason we like macs is that basically you get the benefits of both windows and linux, without much of the fail of either |
| 10:15:47 | <WorkyBob> | indeed |
| 10:16:21 | <Axman6> | though, i do have a wintendo partition now |
| 10:16:35 | <Axman6> | but the windows was free, so... |
| 10:16:36 | <Axman6> | >_> |
| 10:16:47 | <WorkyBob> | what do you need that for Axman6? |
| 10:16:54 | <Neut> | if I win the lottery/find a wad of cash I might just buy one ;) |
| 10:16:58 | <Axman6> | for wintendoing |
| 10:17:10 | <WorkyBob> | oh, I have a PS3 for that |
| 10:17:20 | <WorkyBob> | Neut: meh, the expensive thing is a lie |
| 10:17:28 | <Axman6> | i want a PS3, but only because of the blu-ray and Cell |
| 10:17:51 | <WorkyBob> | you can get them for $600 brand new |
| 10:17:51 | <WorkyBob> | $450 even for refurbs |
| 10:17:54 | <Neut> | WorkyBob: the fact it isn't free makes it expensive for me |
| 10:18:09 | <Axman6> | was your current computer free? |
| 10:18:13 | <WorkyBob> | hardware always costs money |
| 10:18:26 | <Axman6> | not always |
| 10:18:32 | <WorkyBob> | Axman6: meh, BluRay is actually about the only toy I haven't used on it |
| 10:18:41 | <Axman6> | i can see three computers in this room that didn't cost me a cent |
| 10:18:47 | <Neut> | sure wasn't, Im just saying Im not going to buy a new pc sa'll |
| 10:18:52 | <WorkyBob> | ah, k |
| 10:19:00 | <Neut> | dont have the dosh, |
| 10:19:03 | <WorkyBob> | :( |
| 10:19:25 | <WorkyBob> | ACTION wants replicators |
| 10:19:39 | <Axman6> | anyway, back to this assignment |
| 10:19:47 | <Neut> | ditto |
| 10:19:47 | <WorkyBob> | don't you mean binding? |
| 10:19:50 | <WorkyBob> | >.> |
| 10:24:59 | <ivanm> | @seen dibblego |
| 10:25:00 | <lambdabot> | dibblego is in #haskell-in-depth, #xmonad, #functionaljava, #haskell and #scala. I last heard dibblego speak 1h 23m ago. |
| 10:25:11 | <ivanm> | dibblego: isn't it cheating to ask proggit for help on an interview question? :p |
| 10:26:15 | <^Someone^> | Look for dobblego |
| 10:26:33 | <ivanm> | @seen dobblego |
| 10:26:33 | <lambdabot> | dobblego is in #functionaljava, #scala and #haskell. I last heard dobblego speak 25m 19s ago. |
| 10:26:41 | <ivanm> | *shrug* whichever nick he's using ;-) |
| 10:27:01 | <dobblego> | yo |
| 10:27:10 | <ivanm> | isn't it cheating to ask proggit for help on an interview question? :p |
| 10:27:39 | <dobblego> | I've already submitted it -- just playing now :) |
| 10:28:20 | <dobblego> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5373#a5373 |
| 10:28:43 | <ivanm> | heh |
| 10:28:47 | <quicksilver> | well if you can get proggit to help with your interview, then perhaps you can get proggit to help with the job when you get it. So it's not cheating, it's just an indication of one of your skill sets. |
| 10:28:54 | <ivanm> | quicksilver: lol |
| 10:29:12 | <ivanm> | @remember quicksilver well if you can get proggit to help with your interview, then perhaps you can get proggit to help with the job when you get it. So it's not cheating, it's just an indication of one of your skill sets. |
| 10:29:12 | <lambdabot> | Good to know. |
| 10:29:31 | <WorkyBob> | dobblego: perhaps tests might be better with quickcheck and a property that you can convert a number to words and back and get an id function |
| 10:29:33 | <WorkyBob> | and the reverse |
| 10:29:57 | <dobblego> | WorkyBob, g'luck using QC for testing that function |
| 10:30:35 | <dobblego> | WorkyBob, I considered using QC for testing parts of it |
| 10:30:37 | <WorkyBob> | ACTION writes a quick parser for the word based version |
| 10:30:40 | <WorkyBob> | done |
| 10:30:42 | <WorkyBob> | etc... |
| 10:31:23 | <Neut> | btw im doing your exam from last year ;() |
| 10:31:50 | <Axman6> | i think i aced that exam |
| 10:32:04 | <Axman6> | though... i did finish the course with 94%, so there's a good chance :P |
| 10:34:31 | <Saizan> | is there a general name for the kind of testing QuickCheck does? |
| 10:34:43 | <Axman6> | excessive |
| 10:34:46 | <Axman6> | >_> |
| 10:35:28 | <dobblego> | automated specification-based testing |
| 10:36:29 | <Saizan> | looks like it, thanks |
| 10:39:56 | <ivanm> | dobblego: well, I'd _hope_ you'd know :p |
| 10:40:25 | <ivanm> | dobblego: though that guy I was telling you about that loves C# wanted to know why you listed NUnit (I think... one of them) as a "manual" test tool |
| 10:40:40 | <dobblego> | because it is? |
| 10:40:47 | <dobblego> | what guy who what? |
| 10:41:01 | <ivanm> | at dinner, I was saying about a guy that loves C# |
| 10:41:15 | <dobblego> | I've considered writing a proper test automation tool for .NET using C# |
| 10:41:42 | <Axman6> | ivanm: still thinking of coming to ANU? |
| 10:41:50 | <ivanm> | Axman6: yes |
| 10:41:53 | <ivanm> | but it won't be till next year |
| 10:41:55 | <Axman6> | :) |
| 10:42:00 | <dobblego> | a better question might be, "what do you think is automated about nunit?" |
| 10:42:08 | <ivanm> | true |
| 10:42:22 | <Axman6> | i gave a talk today at my uni about how awesome ANU is. (which i think is true, it's an amazing place) |
| 10:42:58 | <Axman6> | campus wide 802.11n wireless with WPA2, connected to a 100mbit internet connection |
| 10:42:58 | <ivanm> | Axman6: I thought you _went_ to ANU... >_> |
| 10:43:15 | <Axman6> | uh, not at my uni, my old college |
| 10:43:28 | <Axman6> | (years 11 and 12) |
| 10:43:39 | <ivanm> | ahhh |
| 10:44:01 | <ivanm> | Axman6: so if you have old HW that can't use WPA, then you can't use wireless at ANU? |
| 10:44:31 | <Axman6> | nah. there's an older network too, but it's less secure and slower |
| 10:44:53 | <Axman6> | and you have tpo log in through a webpage before you can do anything on the network |
| 10:45:21 | <ivanm> | ahhh, fair enough |
| 10:45:24 | <ivanm> | that's what UQ uses |
| 10:45:43 | <ivanm> | PITA, really, when I have to start up a browser just to let my email client work :@ |
| 10:45:58 | <Axman6> | and it's more restrictive. ANU-Secure (the awesome one) is basically a direct net connection, so you can do what ever you want (even torrent at 100mbit) |
| 10:46:11 | <Axman6> | s/net/internet |
| 11:18:57 | <inbuninbu> | i think i've got an interesting problem for you guys... |
| 11:19:12 | <inbuninbu> | my problem is that i want to wait for input, process the input, and output the result |
| 11:19:27 | <inbuninbu> | BUT! some of the evaluation might take a long time, and some of it won't. and i want to output as soon as the result becomes available |
| 11:19:39 | <inbuninbu> | (there will continuously be more chunks of input coming in) |
| 11:19:52 | <inbuninbu> | the crux: i could just use forkIO, but i need to avoid two threads outputting at the same time. |
| 11:20:14 | <inbuninbu> | i could try to implement some kind of concurrent mailbox... but is there a more elegant solution that i'm overlooking? |
| 11:20:54 | <fR0D> | hi i am new to haskell and so i am trying to write programs in it to learn it |
| 11:21:07 | <Baughn> | inbuninbu: The output functions are lazy |
| 11:21:16 | <fR0D> | can someone tell me how to take a series of integers enetered per line |
| 11:21:18 | <Baughn> | inbuninbu: Or, rather, they accept lazy data structures just fine |
| 11:21:25 | <fR0D> | and then process them one by one |
| 11:21:30 | <Baughn> | fR0D: One per line? |
| 11:21:42 | <fR0D> | yes each line has a integer |
| 11:21:53 | <Baughn> | inbuninbu: So "print [1..]", for example, is not going to wait for all of [1..] to be evaluated before it starts printing |
| 11:21:54 | <fR0D> | and say there are n such lines |
| 11:21:55 | <burp> | from stdin or file? |
| 11:22:01 | <fR0D> | stdin |
| 11:22:17 | <Baughn> | fR0D: do ...; int <- fmap read getLine; ... |
| 11:22:24 | <mauke> | readLn |
| 11:22:31 | <Baughn> | ..or that. I keep forgetting that one. |
| 11:22:36 | <mauke> | :t replicateM n readLn |
| 11:22:37 | <lambdabot> | Couldn't match expected type `Int' against inferred type `Expr' |
| 11:22:37 | <lambdabot> | In the first argument of `replicateM', namely `n' |
| 11:22:37 | <lambdabot> | In the expression: replicateM n readLn |
| 11:22:40 | <mauke> | :t replicateM ?n readLn |
| 11:22:41 | <lambdabot> | forall a. (?n::Int, Read a) => IO [a] |
| 11:23:03 | <Baughn> | inbuninbu: That is, of course, assuming that you care about the order of your output |
| 11:23:22 | <inbuninbu> | Baughn: yes that's it exactly. i don't care about the order of my output |
| 11:23:29 | <Baughn> | inbuninbu: If you just want to print stuff as soon as it's evaluated, and don't care about the order, then a mailbox would be best |
| 11:23:57 | <Baughn> | inbuninbu: (But take care to evaluate your data /before/ putting it in the MVar, otherwise it'll just be putting a thunk in there) |
| 11:24:08 | <fR0D> | ok thanks i will try that |
| 11:24:59 | <inbuninbu> | Baughn: i was afraid of that; i was hoping there was some beautiful trick using functors or something that i could use; i guess not |
| 11:25:24 | <Baughn> | inbuninbu: Nope. What you're asking for is basically nondeterminicy |
| 11:25:32 | <Baughn> | inbuninbu: You can't have that outside IO. :) |
| 11:25:36 | <Baughn> | This is a feature. :P |
| 11:25:52 | <Baughn> | inbuninbu: Oh, and be sure to know about the tradeoffs between MVar and Chan |
| 11:26:20 | <inbuninbu> | Baughn: LOL. i thought though, that the list functor sort of provided nondeterminacy in some sense |
| 11:26:56 | <Baughn> | inbuninbu: The list /functor/ just maps. The list applicative instance does, in a sense, but only through providing every possible option. In a deterministic order. |
| 11:27:30 | <Baughn> | inbuninbu: And you're specifically wanting to get the result that evaluates fastest first in your result list. This is very, very indeterminate. |
| 11:27:40 | <Baughn> | inbuninbu: Not referentially transparent at all. :) |
| 11:28:06 | <Baughn> | inbuninbu: If your result values happen to be /equal/ you can use unamb, but I don't expect they are |
| 11:28:41 | <inbuninbu> | Baughn: ok, i think i've got it. at least to move forward. haskell is one deep forest :-) |
| 11:28:57 | <inbuninbu> | Baughn: thanks! |
| 11:31:08 | <Baughn> | inbuninbu: Re: the functor/applicative confusion. I suggest you read the Typeclassopedia. |
| 11:32:11 | <inbuninbu> | Baugn: thanks. actually i started chewing on that earlier today. it helps some, but will take more work on my part to really understand it well |
| 11:37:48 | <ski> | @type Control.Concurrent.mergeIO |
| 11:37:49 | <ski> | @type Control.Concurrent.nmergeIO |
| 11:37:50 | <lambdabot> | forall a. [a] -> [a] -> IO [a] |
| 11:37:51 | <lambdabot> | forall a. [[a]] -> IO [a] |
| 11:38:08 | <ski> | inbuninbu : maybe those're helpful ? |
| 11:38:47 | <inbuninbu> | ski: i saw those, but the documentation is sparse; almost a haiku |
| 11:38:57 | <inbuninbu> | ski: so i'll have to play with them to really understand them, maybe |
| 11:39:59 | <fR0D> | i am still unable to get it, suppose i have to print the sum of all the numbers how will i do it replicateM |
| 11:40:19 | <fR0D> | *using rreplicateM |
| 11:40:21 | <Gracenotes> | :O |
| 11:40:54 | <ski> | compute the sum of the list monadically returned by the call to `replicateM' |
| 11:41:14 | <Gracenotes> | hm. What is mergeIO supposed to do? |
| 11:41:28 | <Gracenotes> | seems to merge two lists concurrently... why would you need it |
| 11:42:22 | <Saizan> | Gracenotes: parallelize the evaluation, i guess |
| 11:43:09 | <ski> | <http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#v%3AmergeIO> "The mergeIO and nmergeIO functions fork one thread for each input list that concurrently evaluates that list; the results are merged into a single output list." |
| 11:43:11 | <Gracenotes> | Saizan: hmmm. *checks out source* |
| 11:43:29 | <shapr> | ACTION boings |
| 11:43:46 | <Gracenotes> | looks complicated. |
| 11:43:57 | <Gracenotes> | uses an MVar and a semaphore |
| 11:45:01 | <Gracenotes> | and involving a function called "suckIO" |
| 11:45:53 | <Gracenotes> | and the MVar seems to be used for an impromptu Chan |
| 11:46:33 | <jacobian> | I haven't really properly though this through yet, but I have a tree which is infinite and lazy, I want to have errors as a I produce the tree, is this difficult? |
| 11:46:58 | <Baughn> | jacobian: No, that's what throw is for |
| 11:47:00 | <jacobian> | And if not, what is an easy approach |
| 11:47:34 | <Gracenotes> | exceptions. breaking control in exceptional cases |
| 11:47:38 | <ivanm> | jacobian: why do you want errors? |
| 11:47:46 | <ivanm> | aren't errors _bad_? :o |
| 11:47:51 | <Baughn> | jacobian: Just realize that since it's lazy, the exceptions will show up as the tree is produced - eg. while it's being consumed |
| 11:48:05 | <Baughn> | Nah, error-throwing from pure code is handy - to point out programming errors |
| 11:48:46 | <jacobian> | So Control.Exception is the way to go |
| 11:48:49 | <Baughn> | jacobian: For pure code, normally you'd augment the structure with some explicit error value. Either or Maybe exist for this purpose |
| 11:48:59 | <Baughn> | Assuming you actually want to handle the error |
| 11:49:10 | <Baughn> | jacobian: Read the documentation for throw carefully |
| 11:49:21 | <Gracenotes> | there's also monads for this |
| 11:49:31 | <eivuokko> | Maybe also a writer monad, if you need "a log." |
| 11:49:34 | <Gracenotes> | er. what he said. |
| 11:50:12 | <jacobian> | I need to give up if something goes wrong, so a log isn't really what I need |
| 11:50:29 | <quicksilver> | Maybe is great for give up if something goes wrong |
| 11:50:36 | <quicksilver> | give up (but with no more information abotu why you did) |
| 11:51:06 | <jacobian> | Information about why would also be useful |
| 11:51:19 | <jacobian> | I was using a hand rolled exception monad previously |
| 11:51:36 | <eivuokko> | And why are you switching off it? |
| 11:51:41 | <ski> | what if part of the tree "goes wrong" but you aren't actually using that part (for one use) ? |
| 11:55:29 | <jacobian> | It should be ok for parts to go wrong that aren't encountered. |
| 12:00:15 | <ivanm> | ^Someone^: surely you can get rid of the last two carets as well... |
| 12:00:56 | <^Someone^> | I think when I tried Someone, it was in use/registered, but it was sometime abck |
| 12:00:57 | <^Someone^> | back* |
| 12:01:05 | <^Someone^> | However, I like this nickname now lol |
| 12:01:58 | <paper_cc> | hmm, is <^Someone^> an infix lifted Someone constructor? |
| 12:02:19 | <ivanm> | paper_cc: can't be infix, it has alphanumeric characters in it |
| 12:02:29 | <quicksilver> | it is infix in that syntax though |
| 12:02:30 | <ivanm> | and constructors have to start with a capital letter |
| 12:02:38 | <mauke> | S is a capital letter |
| 12:02:38 | <quicksilver> | it does. |
| 12:02:39 | <quicksilver> | S |
| 12:02:54 | <ivanm> | quicksilver: it starts with <, not S though... |
| 12:02:58 | <paper_cc> | ivanm: Control.Applicative.Infix defines (<^) and (^>) |
| 12:03:07 | <quicksilver> | no, that parses as <^ Someone ^> |
| 12:03:14 | <quicksilver> | and as paper_cc says.. |
| 12:03:16 | <ivanm> | ahhh |
| 12:03:27 | <ivanm> | ACTION didn't think of that |
| 12:05:46 | <Gracenotes> | but the parsing is only legal if something's on both sides of <^Someone^> |
| 12:06:10 | <Gracenotes> | well. It lexes properly, but there are infixity issues, etc... |
| 12:06:10 | <^Someone^> | Find two girls ; ) |
| 12:06:36 | <Gracenotes> | (blah <^ Someone ^>) isn't a legal section >_> |
| 12:06:42 | <Gracenotes> | <_< |
| 12:07:25 | <ivanm> | @slap ^Someone^ |
| 12:07:26 | <lambdabot> | ACTION smashes a lamp on ^Someone^'s head |
| 12:07:29 | <Gracenotes> | even if blah is a girl |
| 12:07:36 | <^Someone^> | >.> |
| 12:07:41 | <ivanm> | @type (<^) |
| 12:07:43 | <lambdabot> | Not in scope: `<^' |
| 12:07:50 | <ivanm> | @hoogle (<^) |
| 12:07:50 | <lambdabot> | Control.Arrow (<<^) :: Arrow a => a c d -> (b -> c) -> a b d |
| 12:07:56 | <ivanm> | what's just <^ |
| 12:07:58 | <ivanm> | ? |
| 12:07:59 | <paper_cc> | ACTION gives up the idea of lifted Num instances for his Applicative |
| 12:08:08 | <paper_cc> | , [$ty|(<^)] |
| 12:08:09 | <lunabot> | luna: lexical error in string/character literal at end of input |
| 12:08:13 | <Gracenotes> | @hoogle InfixApplicative |
| 12:08:13 | <lambdabot> | No results found |
| 12:08:18 | <Gracenotes> | @hackage InfixApplicative |
| 12:08:19 | <lambdabot> | http://hackage.haskell.org/cgi-bin/hackage-scripts/package/InfixApplicative |
| 12:08:28 | <Gracenotes> | yeah. weird thing. |
| 12:08:41 | <Gracenotes> | but omg ^(+)^ |
| 12:09:01 | <paper_cc> | ivanm: (<^) = flip fmap, (^>) = (<*>) |
| 12:09:21 | <Gracenotes> | it's like liftA2 |
| 12:09:26 | <ivanm> | @type (<*>) |
| 12:09:27 | <lambdabot> | forall (f :: * -> *) a b. (Applicative f) => f (a -> b) -> f a -> f b |
| 12:10:00 | <Gracenotes> | type \f x y -> f <^ x ^> y == type liftA2 |
| 12:10:20 | <paper_cc> | err, x <^f^> y rather? |
| 12:10:38 | <Gracenotes> | oh. right. it's flip fmap. yes |
| 12:10:51 | <ivanm> | Gracenotes: I didn't know there was a type function... |
| 12:10:52 | <ivanm> | ;-) |
| 12:11:03 | <ivanm> | @hoogle type |
| 12:11:04 | <lambdabot> | keyword type |
| 12:11:04 | <lambdabot> | Language.Haskell.TH data Type |
| 12:11:04 | <lambdabot> | Language.Haskell.TH.Syntax data Type |
| 12:11:08 | <paper_cc> | , [$ty|flip fmap] |
| 12:11:09 | <lunabot> | luna: lexical error in string/character literal at end of input |
| 12:11:13 | <paper_cc> | oh |
| 12:11:15 | <Gracenotes> | |] |
| 12:11:20 | <paper_cc> | , [$ty|flip fmap|] |
| 12:11:21 | <Gracenotes> | ivanm: in my imaginary Haskell extension |
| 12:11:23 | <lunabot> | forall a b c . Functor a => a c -> (c -> b) -> a b |
| 12:11:30 | <ivanm> | Gracenotes: ahhh |
| 12:11:34 | <Gracenotes> | :P |
| 12:16:27 | <cnwdup> | When loading haskell code using plugins' make and load_ I get "unknown symbol `base_GHCziBase_unpackCStringzh_closure'" Does anyone know how this can be caused? I do not know what to look for. |
| 12:19:41 | <quicksilver> | JaffaCake: any idea? |
| 12:19:45 | <quicksilver> | dons: ping |
| 12:20:00 | <JaffaCake> | no idea |
| 12:20:06 | <JaffaCake> | ACTION is not plugin-compatible |
| 12:20:17 | <cnwdup> | Lemmih, from the logs I know you have had this issue once. Can you help? |
| 12:21:09 | <paper_cc> | @seen Lemmih |
| 12:21:10 | <lambdabot> | Lemmih is in #haskell. I last heard Lemmih speak 17h 30m 37s ago. |
| 12:29:17 | <paper_cc> | , typ "flip id" |
| 12:29:20 | <lunabot> | "forall b c. b -> (b -> c) -> c" |
| 12:29:26 | <paper_cc> | ivanm: ^^ =) |
| 12:29:46 | <ivanm> | hmmm? |
| 12:30:02 | <paper_cc> | the type function |
| 12:30:21 | <ivanm> | that's a plugin |
| 12:30:24 | <ivanm> | not a function AFAIK |
| 12:30:30 | <paper_cc> | it is. |
| 12:30:47 | <paper_cc> | ACTION is reading $ty quasiquoter code |
| 12:30:51 | <ivanm> | ahhhh |
| 12:31:08 | <mauke> | , typ typ |
| 12:31:10 | <lunabot> | luna: Couldn't match expected type `GHC.Base.String' |
| 12:31:17 | <mauke> | , typ "typ" |
| 12:31:19 | <lunabot> | "GHC.Base.String -> GHC.Base.String" |
| 12:31:33 | <paper_cc> | , typQ "typ" |
| 12:31:36 | <lunabot> | AppT (AppT ArrowT (ConT String)) (ConT String) |
| 12:34:29 | <quicksilver> | lots of the stuff in lunabot is not technically functions |
| 12:34:37 | <quicksilver> | because it's not referentially transparent, etc. |
| 12:34:42 | <quicksilver> | at least - not haskell functions. |
| 12:34:49 | <lars9> | > (*2) 2 |
| 12:34:51 | <lambdabot> | 4 |
| 12:34:54 | <quicksilver> | more like functions on the syntax of haskell. |
| 12:40:14 | <lilac> | , fix typ |
| 12:42:07 | <ivanm> | lilac: which function's type do you want fixed? |
| 12:42:08 | <ivanm> | :p |
| 12:42:56 | <idnar> | haha |
| 12:43:03 | <jacobian> | erg, the most annoying thing about layout is changing the name of things can screw up the code. |
| 12:43:29 | <ivanm> | ACTION agrees |
| 12:43:44 | <ivanm> | it wouldn't be so bad if emacs' haskell-mode could auto-indent properly |
| 12:44:00 | <quicksilver> | ivanm: it can. |
| 12:44:04 | <fasta> | jacobian: like how? |
| 12:44:07 | <quicksilver> | ivanm: if you get the correct indentation package. |
| 12:44:07 | <nvoorhies> | keep hitting tab |
| 12:44:12 | <quicksilver> | @where kuribas-indentation |
| 12:44:12 | <lambdabot> | http://kuribas.hcoop.net/haskell-indentation.el |
| 12:44:17 | <quicksilver> | I don't recommend you keep hitting tab |
| 12:44:19 | <ivanm> | quicksilver: oh? |
| 12:44:25 | <quicksilver> | I recommend you get the better indentation mode :P |
| 12:44:34 | <ivanm> | how do you integrate that into haskell-mode? |
| 12:44:45 | <fasta> | I use Kuribas-indentation, although I hate some features of it deeply. |
| 12:44:57 | <fasta> | E.g. "Illegal token <something>" |
| 12:44:59 | <ivanm> | fasta: oh? which features? |
| 12:45:01 | <quicksilver> | ivanm: I shall paste the relevant parts of my .emacs |
| 12:45:07 | <jacobian> | complaining is always a good idea :) otherwise I'd never have seen that! |
| 12:45:09 | <ivanm> | what does it call an "illegal token"? |
| 12:45:18 | <ivanm> | jacobian: heh |
| 12:45:20 | <mmorrow> | , help |
| 12:45:22 | <lunabot> | type of an expression: , [$ty| \x -> x |] |
| 12:45:22 | <lunabot> | get info for a type/class: , src ''Monad |
| 12:45:22 | <lunabot> | get info for a var/con: , src 'fix |
| 12:45:54 | <fasta> | ivanm: in short, its parser is broken. As a result you get those errors. |
| 12:46:17 | <fasta> | ivanm: I have a complete example, if you really want it. |
| 12:46:25 | <ivanm> | fasta: but its parser must be better than the default one if its indentation stuff is better? |
| 12:46:47 | <quicksilver> | ivanm: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5374#a5374 |
| 12:46:59 | <quicksilver> | its parser is better, but it is more painful when you find bugs in it |
| 12:47:06 | <mmorrow> | ACTION realizes that no one actually needed any help |
| 12:47:08 | <quicksilver> | it is pretty unrepetent when it fails. |
| 12:47:22 | <ivanm> | quicksilver: *nod* |
| 12:47:25 | <quicksilver> | to be fair, kuribas fixed both bugs I found within a day. |
| 12:47:31 | <quicksilver> | and I think he fixed one of fasta's bugs |
| 12:47:43 | <quicksilver> | I'm sure he'd be open to fixing whichever one is bothering fasta now :) |
| 12:47:54 | <fasta> | quicksilver: oh, he did? :) I didn't know he was developing it. |
| 12:48:04 | <mmorrow> | paper_cc: did you find the $ty code somewhere? |
| 12:48:08 | <quicksilver> | he's not developing it into new exciting directions |
| 12:48:15 | <quicksilver> | but he is fixing bugs as they are reported. |
| 12:48:20 | <ivanm> | quicksilver: just bug fixing? |
| 12:48:25 | <fasta> | quicksilver: that's good enough for me for now |
| 12:48:29 | <quicksilver> | I think stefan said it's going into the next release of haskell-mode, too. |
| 12:48:32 | <ivanm> | is it going to be integrated into haskell-mode anytime soon? |
| 12:48:35 | <fasta> | ACTION happily installs the new version |
| 12:48:38 | <mmorrow> | paper_cc: i need to put the rest of lunabot stuff into the repo (which currently just has the bare (rewritten) infrastructure) |
| 12:48:57 | <ivanm> | quicksilver: are you psychic? :o |
| 12:49:06 | <ivanm> | you answered my question before I asked it! :o |
| 12:49:07 | <paper_cc> | mmorrow: looks like you put it on hpaste about 3 months ago |
| 12:49:13 | <paper_cc> | mmorrow: http://moonpatio.org/fastcgi/hpaste.fcgi/view?id=1514 |
| 12:49:16 | <mmorrow> | paper_cc: nice, totally |
| 12:49:16 | <quicksilver> | ivanm: no, it's just network lag that makes it seem that way to you. |
| 12:49:21 | <quicksilver> | ivanm: relativity is a bitch. |
| 12:49:30 | <quicksilver> | actually I had 2 hours to research the answr and reply to you. |
| 12:49:31 | <ivanm> | network lag of something _I_ said? :o |
| 12:49:38 | <ivanm> | heh |
| 12:49:41 | <mmorrow> | hpaste2search++ |
| 12:50:45 | <mmorrow> | paper_cc: ooh, that code needs to be cleaned :) |
| 12:51:31 | <paper_cc> | mmorrow: that code looks evil :( |
| 12:52:10 | <fasta> | ivanm: you should just be less predictable. ;) |
| 12:52:10 | <paper_cc> | , (\[$ty|foo|] -> "bar") "baz" |
| 12:52:12 | <lunabot> | luna: <interactive>:1:51-70: Non-exhaustive patterns in lambda |
| 12:52:17 | <mmorrow> | hehe |
| 12:52:21 | <paper_cc> | , (\[$ty|foo|] -> "bar") "zOMG epic fail." |
| 12:52:23 | <lunabot> | "bar" |
| 12:52:25 | <mmorrow> | haha |
| 12:52:42 | <ivanm> | fasta: heh |
| 12:53:03 | <ivanm> | quicksilver: would you know how much of that is necessary? |
| 12:53:14 | <quicksilver> | of my paste? |
| 12:53:18 | <ivanm> | yeah |
| 12:53:27 | <ivanm> | I don't have any auto-mode-alist in my config, but it's still loaded |
| 12:53:36 | <ivanm> | IIRC, I use the haskell-site-file that comes with haskell-mode |
| 12:53:39 | <quicksilver> | then you don't need that. |
| 12:53:49 | <ivanm> | *nod* |
| 12:53:50 | <quicksilver> | I can certainly tell you what every line does :) |
| 12:53:59 | <ivanm> | heh |
| 12:54:06 | <quicksilver> | the autoloads set up certain files to be launched when certain symbols are called as functions. |
| 12:54:20 | <ivanm> | what's max-lisp-eval-depth for? |
| 12:54:27 | <quicksilver> | the -mode-hook makes sure all my haskell buffers have doc-mode, decl-scan and indentation-mode |
| 12:54:31 | <quicksilver> | the parser is rec-descent |
| 12:54:39 | <quicksilver> | I tend to write very deep haskell expressions |
| 12:54:49 | <ivanm> | *nod* |
| 12:55:05 | <quicksilver> | so the default level wasn't enough |
| 12:55:06 | <McManiaC> | how can i easily download the whole sourcecode of the standard lib? is there something like darcs for that? |
| 12:55:33 | <fasta> | quicksilver: what is the default level? |
| 12:55:41 | <mmorrow> | @where+ lunabot http://moonpatio.com/repos/lunabot/ {- currently just the bare bot + ghc-api-eval + eval-rlimit-sandboxed-stdin->stdout (and no docs) -} |
| 12:55:42 | <lambdabot> | Done. |
| 12:55:45 | <fasta> | quicksilver: 900 seems a bit high. |
| 12:56:08 | <fasta> | quicksilver: 600 |
| 12:56:14 | <fasta> | quicksilver: never mind. And o.O |
| 12:56:45 | <mmorrow> | quicksilver: select! http://moonpatio.com/repos/lunabot/Dup.hs |
| 12:56:56 | <mmorrow> | (stolen from oleg) |
| 12:57:06 | <ivanm> | quicksilver: so I replace this with kuribas' indentation? (add-hook 'haskell-mode-hook 'turn-on-haskell-indent) |
| 12:58:40 | <Saizan> | McManiaC: each package has its own repo |
| 12:58:43 | <hackagebot> | Emping 0.6 |
| 12:58:55 | <Saizan> | McManiaC: they live under darcs.haskell.org/libraries/ |
| 13:02:11 | <ivanm> | "haskell-indent-region: Auto-reindentation of a region is not supported" :( |
| 13:02:30 | <ivanm> | at least it shows kuribas' mode is loaded |
| 13:03:44 | <hackagebot> | explicit-sharing 0.4.0.1 |
| 13:03:49 | <quicksilver> | mmorrow: awesome. |
| 13:04:06 | <quicksilver> | ivanm: learn how to use indent-rigidly if you want to move regions left + right |
| 13:04:08 | <McManiaC> | Saizan: darcs get darcs.haskell.org/libraries/getopt/ for example? |
| 13:04:12 | <quicksilver> | ivanm: or the rectangle commands |
| 13:04:21 | <McManiaC> | darcs failed: Not a repository: darcs.haskell.org/libraries/haskell98 (darcs.haskell.org/libraries/haskell98/_darcs/inventory: openBinaryFile: does not exist (No such file or directory)) |
| 13:04:25 | <McManiaC> | is what i get |
| 13:04:25 | <quicksilver> | ivanm: C-4 C-x TAB = region 4 places to the right. |
| 13:04:30 | <ivanm> | quicksilver: I wanted to try re-indenting my entire file ;-) |
| 13:04:32 | <McManiaC> | s/haskell98/whatever ^^ |
| 13:04:45 | <Saizan> | McManiaC: with http:// in front |
| 13:05:01 | <McManiaC> | ah! great :) |
| 13:05:11 | <paper_cc> | is it possible to extend wxHaskell bindings? |
| 13:06:07 | <paper_cc> | ACTION wants dockable windows from contrib/fl but doesn't know how the bindings are actually generated |
| 13:09:20 | <shapr> | @seen pesco |
| 13:09:20 | <lambdabot> | I haven't seen pesco. |
| 13:10:36 | <cnwdup> | Is it possible to express this pattern: \dyn -> maybe (maybe (...) (doSomethingElse) (fromDynamic dyn)) (doSomething) (fromDynamic dyn) into something like handle [doSomething, doSomethingElse] msg? |
| 13:11:09 | <cnwdup> | Or is there another convenient way to avoid boilerplate? |
| 13:11:48 | <cnwdup> | doSomething, doSomethingElse :: a -> m (), although not of the same a. |
| 13:12:09 | <fasta> | cnwdup: sounds like you need rank-2 types. |
| 13:12:26 | <paper_cc> | cnwdup: you can wrap doSomething* into Dynamic too if they are monomorphic |
| 13:12:42 | <paper_cc> | cnwdup: (if you're sure you really need dynamics) |
| 13:12:57 | <ivanm> | kuribas' mode isn't perfect, it still seems to be doing the whole indentation-cycle stuff |
| 13:13:07 | <cnwdup> | paper_cc, for the signals (dyn), yes. |
| 13:13:18 | <cnwdup> | Thanks. I'll use that approach if I cannot get it working with rank-2 types. |
| 13:14:00 | <lilac> | you might be able to do something with an existential list type |
| 13:14:56 | <nibro> | what's the language flag to GHC to enable generalized list comprehensions? |
| 13:15:17 | <nibro> | the docs don't say, and there doesn't seem to be a suitable one in Language.Haskell.Extension in cabal |
| 13:15:36 | <ivanm> | nibro: you mean the pragma to use in 6.10? |
| 13:15:36 | <lilac> | looks like you want a list :: [exists a. Typeable a => a -> b] |
| 13:15:40 | <quicksilver> | ivanm: it doesn't cycle in the same way. It's always TAB for the next valid position to the right, and BACKSPACE for the next valid position to the left |
| 13:16:04 | <quicksilver> | ivanm: much more consistent. It's also much better at getting a concise list of valid positions. |
| 13:16:05 | <dcoutts> | nibro: ParallelListComp |
| 13:16:16 | <ivanm> | quicksilver: unless the two modes are interfering, since I haven't restarted emacs since I put that in |
| 13:16:32 | <nibro> | dcoutts: so ParallelListComp enables both parallel and generalized comprehensions? |
| 13:16:35 | <ivanm> | quicksilver: is there actually any docs for this? |
| 13:16:53 | <cnwdup> | lilac, that gives me a parse error on `.'. |
| 13:16:54 | <dcoutts> | nibro: oh, no sorry, perhaps they have not registered one. Is it in a released ghc yet? |
| 13:17:02 | <quicksilver> | ivanm: only what is readable in the lisp source |
| 13:17:16 | <quicksilver> | ivanm: you probably need to turn off the old indent mode |
| 13:17:19 | <ivanm> | oh, if backspace is back one indent, how do you delete the char to the left of the cursor? |
| 13:17:36 | <quicksilver> | it's only back one indent if the cursor is at the beignning of a line |
| 13:17:44 | <quicksilver> | (beginning except for the intiial indentation, that is) |
| 13:17:44 | <nibro> | dcoutts: not sure, I'm just reading the docs, there's no mention of a version or that it's not yet supported |
| 13:18:02 | <dcoutts> | nibro: you're looking at the user guide for 6.10? |
| 13:18:14 | <nibro> | http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html |
| 13:18:20 | <nibro> | I believe so |
| 13:18:36 | <ivanm> | quicksilver: *nod* |
| 13:19:21 | <dcoutts> | nibro: bah, they're being naughty |
| 13:19:42 | <dcoutts> | nibro: no hackage packages can use that extension therefore |
| 13:19:58 | <nibro> | dcoutts: I wonder if that's deliberate... :) |
| 13:20:04 | <dcoutts> | heh |
| 13:20:21 | <ivanm> | what? what can't a hackage package use? |
| 13:20:32 | <nibro> | generalized list comprehensions |
| 13:20:55 | <ivanm> | why doesn't hackage accept them? |
| 13:20:58 | <nibro> | I can dig around in the ghc source to see what they're doing there |
| 13:21:04 | <dcoutts> | nibro: please |
| 13:21:16 | <nibro> | ivanm: because the extension is not registered with cabal, so cabal wouldn't recognize the flag |
| 13:22:26 | <cnwdup> | Reading the Rank-N types wiki article: One can unpack existential types? |
| 13:22:51 | <ivanm> | nibro: as in a compile-time-flag? |
| 13:23:03 | <ivanm> | would it accept it if it's listed as a PRAGMA in the actual source file? |
| 13:23:30 | <fasta> | cnwdup: you cannot unpack existential types. |
| 13:23:40 | <quicksilver> | well, arguably that's what "case" does |
| 13:23:44 | <quicksilver> | it depends what you think unpacking means. |
| 13:24:09 | <nibro> | ivanm: as in a flag corresponding to -XParallelListComp for the parallel ones |
| 13:24:09 | <cnwdup> | quicksilver, then how can Iunpack a type and how I cannot? |
| 13:24:50 | <nibro> | ivanm: yes, a source pragma would still work, but that's assuming that there actually is a flag to use |
| 13:25:07 | <quicksilver> | cnwdup: case x of MkFoo y -> .... |
| 13:25:14 | <nibro> | ivanm: and since GHC supposedly defers to cabal for the flags, that doesn't seem like it would be the case |
| 13:25:23 | <quicksilver> | where MkFoo is the constructor of an existential |
| 13:25:33 | <quicksilver> | is one possible interpretation of the phrase "unpack an existential" |
| 13:25:46 | <cnwdup> | Ah, but I cannot pattern match against y, right? |
| 13:26:28 | <cnwdup> | Although -- as I understand the example given on the Rank-N types page -- I can. Oo |
| 13:27:09 | <cnwdup> | Ah, my bad. No it doesn't suggest that. |
| 13:27:13 | <quicksilver> | depends what you think pattern match means. |
| 13:27:22 | <quicksilver> | case x of MkFoo y -> *is* a pattern match. |
| 13:27:28 | <dcoutts> | nibro: ohhh, it's called TransformListComp |
| 13:27:43 | <dcoutts> | nibro: but has no documentation |
| 13:27:55 | <quicksilver> | case x of MkFoo (y:ys) -> would be a more complex pattern match, and still permitted. |
| 13:28:03 | <quicksilver> | (if it made type-sense) |
| 13:28:19 | <quicksilver> | what you can't do is unpack the MkFoo constructor with a let. It has to be a case. |
| 13:29:05 | <cnwdup> | But I cannot do case foo of MkFoo (Bar a b) -> ...; MkFoo (Baz a) -> ...? |
| 13:29:41 | <nibro> | dcoutts: Transform O_o |
| 13:29:44 | <dcoutts> | nibro: you might like to point out on the ghc users list that it's a silly name given what it's called everywhere else |
| 13:30:00 | <dcoutts> | nibro: adding new alias and deprecating old ones is possible |
| 13:30:25 | <nibro> | dcoutts: indeed, it sounds like a verb form of the "AllowOverlappingInstances" style rather than the nicer "OverlappingInstances" kind |
| 13:30:38 | <dcoutts> | nibro: it's also annoying that in the user guide where the extensions are described the extension name is not given. |
| 13:30:48 | <nibro> | dcoutts: I'll flag this on the ghc list |
| 13:30:50 | <dcoutts> | nibro: the state of docs for the extensions is pretty poor |
| 13:31:23 | <dcoutts> | nibro: perhaps we can shame someone into cross referencing them and adding haddock docs for the existing ones in Language.Haskell.Extension |
| 13:32:54 | <nibro> | dcoutts: maybe I should wait to post until I've gone through the whole documentation, there may be more rocks to overturn... ;-) |
| 13:33:08 | <dcoutts> | nibro: I expect there are |
| 13:33:19 | <dcoutts> | nibro: a barrage of complaint is no bad thing though :-) |
| 13:33:20 | <nibro> | fun times ahead then :) |
| 13:33:37 | <nibro> | indeed, criticism is only healthy :-) |
| 13:34:03 | <quicksilver> | cnwdup: you can do that, yes. |
| 13:34:12 | <quicksilver> | cnwdup: or, I'd be surprised if you couldn't. |
| 13:34:58 | <cnwdup> | quicksilver, http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2520#a2520 ghci doesn't like that. |
| 13:35:44 | <RayNbow> | > let weird ~(x,y) = (1,x); crazy = weird crazy in crazy |
| 13:35:46 | <lambdabot> | (1,1) |
| 13:36:08 | <RayNbow> | > let weird (x,y) = (1,x); crazy = weird crazy in crazy -- this crashes GHC 6.10.1 in Windows :p |
| 13:36:13 | <nibro> | ACTION thinks there should be an NPlusK flag |
| 13:36:13 | <lambdabot> | mueval-core: Prelude.read: no parse |
| 13:36:13 | <lambdabot> | mueval: ExitFailure 1 |
| 13:37:40 | <quicksilver> | cnwdup: yes, but that's not becausey ou can't use case on them |
| 13:37:44 | <astrobunny> | phew. parsec is pretty cool. |
| 13:37:48 | <quicksilver> | cnwdup: it's because you don't know what type is inside the box. |
| 13:37:52 | <cnwdup> | quicksilver, ok |
| 13:37:52 | <astrobunny> | i never thought i would write parsers like this |
| 13:38:28 | <quicksilver> | cnwdup: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2520#a2521 |
| 13:38:51 | <cnwdup> | quicksilver, ok. Now I get what you meant. |
| 13:38:52 | <cnwdup> | Thanks. |
| 13:38:54 | <quicksilver> | cnwdup: example of how you can pattern match through an existential. |
| 13:39:08 | <quicksilver> | cnwdup: what you tried to do was take a different branch depending what the actual type in the box was. |
| 13:39:13 | <quicksilver> | cnwdup: you can't do that, because you don't know |
| 13:39:24 | <quicksilver> | nobody knows what the type is inside the box :) |
| 13:39:31 | <quicksilver> | this is the problem that Typeable solves |
| 13:39:44 | <quicksilver> | - giving you a reification for every type so you can dispatch on that. |
| 13:39:51 | <quicksilver> | it's a pretty big hammer, though. |
| 13:47:59 | <nibro> | hmm, unboxed tuples (# x, y #) are presumably enabled with UnboxedTuples, but the docs say the (# and #) lexemes are enabled by MagicHash |
| 13:48:27 | <nibro> | when would you ever want those lexemes without UnboxedTuples, and vice versa? |
| 13:50:06 | <Baughn> | nibro: For functions with # in the name |
| 13:50:28 | <Baughn> | touch#, unsafeCoerce#, etc. |
| 13:51:15 | <ivanm> | with # denoting unboxed? |
| 13:51:22 | <Baughn> | No, denoting internal |
| 13:51:36 | <nibro> | Baughn: sure, I'm aware of those, what I meant was that (# #) lexemes have no use if UnboxedTuples aren't on, and you can't use UnboxedTuples without the (# #) lexemes, or? |
| 13:52:00 | <Baughn> | nibro: The lexeme MagicHash turns on is #, not (# |
| 13:52:35 | <Baughn> | (# is a combination of two lexemes |
| 13:53:02 | <nibro> | Baughn: nope |
| 13:53:18 | <nibro> | Baughn: you can still use # as an operator with MagicHash on |
| 13:53:37 | <nibro> | Baughn: and the Lexer generator lists the lexemes as (# and #) |
| 13:53:48 | <Baughn> | Hm. Well, that's odd then |
| 13:54:08 | <nibro> | Baughn:... but now you got me to look at the source, which solved the mystery |
| 13:54:10 | <fasta> | Is there a zip type class? |
| 13:54:10 | <nibro> | :) |
| 13:54:35 | <nibro> | Baughn: those things *are* enabled by the UnboxedTuples extension, it's just the docs that are wrong |
| 13:54:48 | <fasta> | There is a type class for map, fold, filter, with some trouble, but no zips, AFAIK. |
| 13:55:03 | <nibro> | fasta: what would you want to parametrize the class over? |
| 13:55:40 | <fasta> | nibro: I can write it myself, that is not the problem. But I was thinking of e.g. zipping a Data.Sequence. |
| 13:56:01 | <fasta> | nibro: or zipping arrays |
| 13:56:07 | <nibro> | fasta: right, I see, that's not an unreasonable idea I guess |
| 13:56:13 | <fasta> | nibro: really, there is a lot of things one could zip. |
| 13:56:32 | <nibro> | fasta: I would guess Data.Sequence already has a zip-like function, no? |
| 13:57:06 | <fasta> | nibro: it doesn't. |
| 13:57:37 | <fasta> | nibro: you can easily write one, though, which is what I did now, but this was not just about Data.Sequence. |
| 13:58:07 | <quicksilver> | fasta: you can zip an arbitrary Traversable with an arbitrary Foldable |
| 13:58:16 | <quicksilver> | fasta: my code for this is on the wiki |
| 13:58:40 | <quicksilver> | zipWithTF :: (Traversable t,Foldable f) => (a -> b -> c) -> t a -> f b -> t c |
| 14:00:03 | <quicksilver> | although some unmentionable "improved" my code by replacing it with a less clear version which uses an unnecessarily generic monad while my version used a neat supply monad. |
| 14:00:07 | <quicksilver> | but that's wikis for you. |
| 14:00:44 | <fasta> | quicksilver: why don't you put it on hackage? It certainly is more useful than hnop. |
| 14:00:59 | <quicksilver> | seems silly to put a single function on hackage. |
| 14:01:07 | <quicksilver> | If anything it should just go into Traversable |
| 14:01:17 | <quicksilver> | http://www.haskell.org/haskellwiki/Foldable_and_Traversable |
| 14:02:45 | <fasta> | quicksilver: it's not silly. Putting a package that does not compile on hackage is silly. |
| 14:03:01 | <nibro> | infix type constructors are enabled by -XTypeOperators ? |
| 14:03:14 | <quicksilver> | something else being *more* silly is not a good enough reason ;) |
| 14:05:20 | <nibro> | apparently they are on by default. Hrm! |
| 14:06:30 | <fasta> | quicksilver: it's just less work to do cabal install $function than to do copy paste. Also, think of the network effects. When someone just browses Hackage they might think, oh, that's nice and install it. As a result more code becomes more general. |
| 14:07:09 | <Baughn> | Well, except in practice Hackage is becoming too big to just browse. :) |
| 14:07:17 | <dcoutts> | search! |
| 14:07:22 | <quicksilver> | yes, but I think those advantages are also observed if I get the functions added to Data.Traversable itsel. |
| 14:07:24 | <dcoutts> | hoogle/hayoo |
| 14:07:38 | <_SamB_> | maybe it's just too disorganized |
| 14:07:56 | <dcoutts> | ACTION agrees with quicksilver |
| 14:08:14 | <nibro> | dcoutts: is there a reason why infix type constructors are allowed without naming a specific extension? |
| 14:08:15 | <fasta> | quicksilver: yes, that would even be better. |
| 14:08:41 | <fasta> | And there are too many (useless) packages on Hackage too. |
| 14:08:41 | <nibro> | dcoutts: I'm letting you answer to all the sins of the GHC team here ;) |
| 14:08:54 | <ivanm> | quicksilver: why do you use (lambda nil haskell-indentation-mode)? |
| 14:09:12 | <dcoutts> | nibro: sorry, you'll have to ask on the ghc list or ask JaffaCake in #ghc |
| 14:09:32 | <nibro> | dcoutts: alright, I'll do that |
| 14:10:55 | <quicksilver> | ivanm: because there isn't (or wasn't) a turn-on-haskell-indentation-mode I could use. |
| 14:10:57 | <jav> | Hi there! cabal question: My application includes a shell script that I would like to have installed in some way alongside the main program. How do I go about this? Is this some sort of special 'executable' or a 'data file' or something? |
| 14:11:18 | <ivanm> | quicksilver: you can't just use it directly? seems to be working here... >_> |
| 14:11:29 | <quicksilver> | then i dunno ;) |
| 14:11:47 | <ivanm> | heh |
| 14:11:49 | <ivanm> | also, why do you make (quote (...)) explicit rather than just '(..) ? |
| 14:11:58 | <dev31212> | hi all |
| 14:12:08 | <ivanm> | quicksilver: ahhh, looks like there is now |
| 14:12:12 | <ivanm> | turn-on-haskell-indentation |
| 14:12:17 | <dev31212> | is there any standard, sort of scientigfic process for identifying redundant cases in functions |
| 14:12:20 | <dev31212> | and reducing them out? |
| 14:13:08 | <dev31212> | Like one might perform in binary algebra, etc.. |
| 14:13:43 | <doserj> | ACTION remembers why he doesn't use haskell-indentation-mode. It somehow kills delete-selection-mode... |
| 14:14:42 | <Baughn> | Ugh, delete-selection mode.. |
| 14:15:04 | <Baughn> | I need to mark regions for so many /other/ reasons than copying them, that would make me lose my mind. :/ |
| 14:15:20 | <ivanm> | quicksilver: I take it back... the documentation says it's there, but it isn't :s |
| 14:15:37 | <dev31212> | Is there any such proecess, or must I rely on intuition and experience? |
| 14:15:39 | <dev31212> | Which is fine |
| 14:15:41 | <ivanm> | doserj: oh? what's delete-selection-mode? selecting something and pressing delete/backspace to delete it? |
| 14:15:47 | <dev31212> | Just thought there might be some method to this |
| 14:15:48 | <Baughn> | dev31212: In the absence of guards, it should be possible to automate it. With guards.. |
| 14:16:01 | <dev31212> | hmmm |
| 14:16:03 | <Baughn> | dev31212: Well, -Wall does some of it (without guards) |
| 14:16:03 | <doserj> | ivanm: yes |
| 14:16:23 | <dev31212> | Baugn, I see, thanks |
| 14:16:38 | <Baughn> | I think it assumes guards are always true, though |
| 14:16:55 | <dev31212> | ok |
| 14:17:57 | <fasta> | quicksilver: The generic filter definition seems to be wrong: filter (>(23::Int)) [1..50] :: (Control.Applicative.Applicative f, |
| 14:17:57 | <fasta> | Monoid (f Int)) => |
| 14:17:57 | <fasta> | f Int |
| 14:18:21 | <fasta> | quicksilver: or is it so general that it also overloads on the return container? |
| 14:19:13 | <fasta> | Oh, yes, it appears it does that. It's not something I like :) |
| 14:22:30 | <quicksilver> | yes that was more by way of example |
| 14:22:51 | <quicksilver> | it wasn't clear what would be useful. |
| 14:25:25 | <fasta> | quicksilver: a filter which returns the same type as it got would make sense to me. No unresolved overloading errors etc. |
| 14:27:17 | <dev31212> | If I post a small code segment, Baugn, would you mind just taking a quick look to see if it can be reduced? |
| 14:27:20 | <dev31212> | Its just 15 lines |
| 14:27:24 | <Zao> | dev31212: hpaste it. |
| 14:27:30 | <dev31212> | The code works, I just dont want to enforce bad habits |
| 14:27:31 | <dev31212> | ok Zao |
| 14:28:46 | <dev31212> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5375#a5375 |
| 14:28:51 | <dev31212> | Ok I posted the whole thing actually |
| 14:29:02 | <dev31212> | The function I am seeing if it is reducible is the my_remove function |
| 14:29:07 | <dev31212> | which removes an elemt from the list. |
| 14:29:44 | <quicksilver> | fasta: well if you constrain its type signature, it does? |
| 14:29:57 | <quicksilver> | @type foldMap |
| 14:29:58 | <lambdabot> | Not in scope: `foldMap' |
| 14:30:08 | <fasta> | quicksilver: yes, that's what I did a few minutes ago. |
| 14:30:21 | <Apocalisp> | @type Foldable.foldMap |
| 14:30:22 | <quicksilver> | my code has the type sig constrained too :) |
| 14:30:22 | <lambdabot> | Couldn't find qualified module. |
| 14:30:28 | <Apocalisp> | @type data.Foldable.foldMap |
| 14:30:29 | <lambdabot> | parse error on input `data' |
| 14:30:49 | <fasta> | quicksilver: there was no Applicative instance for Data.Sequence, so, I just wrote one. Although, I haven't checked the laws. |
| 14:30:54 | <Apocalisp> | @type Data.Foldable.foldMap |
| 14:30:56 | <lambdabot> | forall a m (t :: * -> *). (Data.Foldable.Foldable t, Monoid m) => (a -> m) -> t a -> m |
| 14:31:00 | <Apocalisp> | \o/ |
| 14:31:08 | <doserj> | dev31212: typically you don't have to pattern match on the case for a single element list. |
| 14:31:19 | <Berengal> | Is there a way to hide a package in just one module? |
| 14:32:04 | <doserj> | dev31212: my_concat just seems wrong. |
| 14:32:30 | <Saizan> | Berengal: tried {-# OPTIONS_GHC -hide-package foo #-} ? |
| 14:33:29 | <dev31212> | doserj, yeah Im looking at my_remove at the moment though |
| 14:33:40 | <dev31212> | doserj, ok |
| 14:33:53 | <dev31212> | yeah I wwas thinking single ement matching might noit be needed |
| 14:34:29 | <Berengal> | Saizan: That tells me "unknown flag" |
| 14:34:52 | <dev31212> | ok, let me see if I can remove the single element case |
| 14:35:58 | <doserj> | dev31212: you expect my_remove to be called with counter = 0? |
| 14:36:32 | <dev31212> | yes doserj |
| 14:36:42 | <dev31212> | I could add another wrapper to do that by default |
| 14:36:55 | <dev31212> | the function is my_remove; |
| 14:36:58 | <lilac> | fasta: if you used the normal Applicative instance for Monads, it will obey the laws |
| 14:36:59 | <dev31212> | my_remove' |
| 14:37:10 | <dev31212> | I was going to add simply My_remove which calls it with 0 for the counter |
| 14:37:22 | <cnwdup> | > (+1, 'h':) &&& (42, "ello") |
| 14:37:23 | <lambdabot> | A section must be enclosed in parentheses thus: (+ 1)A section must be encl... |
| 14:37:35 | <cnwdup> | > ((+1), ('h':)) &&& (42, "ello") |
| 14:37:36 | <lambdabot> | No instance for (Control.Arrow.Arrow (,)) |
| 14:37:36 | <lambdabot> | arising from a use of `Control... |
| 14:37:44 | <doserj> | dev31212: well, instead of incrementing counter and testing index==counter, you can also decrement index, and test index==0 |
| 14:37:48 | <cnwdup> | Mh, what was the function to change both values of a tupel? |
| 14:37:51 | <fasta> | lilac: What do you mean? I haven't really used Applicatives. |
| 14:37:57 | <dev31212> | soderj, ahh! |
| 14:38:03 | <dev31212> | thanks, thats much better |
| 14:38:36 | <lilac> | fasta: instance Monad m => Applicative m where pure = return; (<*>) = ap |
| 14:38:50 | <fasta> | lilac: but Sequence is not a monad. |
| 14:39:05 | <fasta> | lilac: never mind |
| 14:39:08 | <fasta> | lilac: it is. |
| 14:40:07 | <doserj> | dev31212: of course, then you can directly pattern match agains 0, instead of having a guard |
| 14:40:11 | <lilac> | fasta: remember that a Seq is semantically just a stricter form of [] |
| 14:41:14 | <fasta> | lilac: What exactly does an Applicative do? Pure is obvious, but <*>? |
| 14:41:22 | <quicksilver> | fasta: ap |
| 14:41:23 | <quicksilver> | :t ap |
| 14:41:24 | <lambdabot> | forall (m :: * -> *) a b. (Monad m) => m (a -> b) -> m a -> m b |
| 14:41:25 | <fasta> | lilac: I thought it was just like fmap |
| 14:41:36 | <dev31212> | doserj, right |
| 14:41:41 | <dev31212> | sounds much better |
| 14:41:41 | <fasta> | :t fmap |
| 14:41:42 | <lambdabot> | forall a b (f :: * -> *). (Functor f) => (a -> b) -> f a -> f b |
| 14:41:49 | <dev31212> | thats exactly the jkind of info I needed |
| 14:41:51 | <dev31212> | best practices |
| 14:41:53 | <dev31212> | thanks |
| 14:42:06 | <quicksilver> | fasta: instead of defining applicative with pure + <*>, you can define it with pure + sequence |
| 14:42:10 | <doserj> | fasta: (<*>) = ap = liftM2 ($) |
| 14:42:15 | <quicksilver> | fasta: maybe that's a better intuition. |
| 14:42:32 | <quicksilver> | fasta: ... it says you can run lots of actions, one after another, but none of them depends on the results of the earlier ones |
| 14:42:41 | <quicksilver> | (i.e. you accumulate all the results in a list) |
| 14:42:41 | <fasta> | quicksilver: but if they are the same, why don't we just have deriving Applicative? |
| 14:42:50 | <fasta> | Or just dump Applicative? |
| 14:42:58 | <quicksilver> | it's not the same as monad |
| 14:43:01 | <Berengal> | Saizan: I got it working with {-# OPTIONS_GHC -ignore-package=foo #-} |
| 14:43:03 | <quicksilver> | sequence isn't engouhg to define monad |
| 14:43:09 | <quicksilver> | you can't derive >>= from sequence |
| 14:43:12 | <quicksilver> | which is rather the point, here. |
| 14:43:29 | <quicksilver> | monads can use the result of earlier effects in later effects |
| 14:43:33 | <quicksilver> | applicatives can't. |
| 14:43:39 | <quicksilver> | actually the paper is rather readable. |
| 14:44:39 | <fasta> | I never ran into any performance problems with monads, so when I read the Applicative paper, it seemed kind of pointless. |
| 14:45:04 | <fasta> | Actually, I had some laziness issuess, but nothing with parsers or anything like that. |
| 14:45:04 | <byorgey> | performance isn't the issue. |
| 14:45:23 | <fasta> | For _high-performance_ parsing, I would not use Haskell. |
| 14:45:26 | <byorgey> | or at least, not the only one. |
| 14:45:39 | <byorgey> | Applicative often lets you code things in a more natural (*applicative*) style. |
| 14:45:50 | <Berengal> | Saizan: Actually, I didn't... It doesn't complain, but it doesn't hide the package either |
| 14:46:27 | <quicksilver> | byorgey: not really, you can code in that style with monads too :P |
| 14:46:36 | <lilac> | fasta: <*> applies a function in the functor to a value in the functor to produce a result in the functor |
| 14:46:43 | <quicksilver> | byorgey: I think that's not really the point of applicative, although it's possible an insight Applicative makes. |
| 14:46:52 | <fasta> | byorgey: doserj defined one of the methods in terms of monads and the other one is equivalent to return. |
| 14:47:03 | <gwern> | @quote stricter |
| 14:47:03 | <lambdabot> | gwern says: the best way to optimize a program is to make it lazier or stricter. |
| 14:47:06 | <fasta> | byorgey: or what quicksilver said. |
| 14:47:29 | <quicksilver> | the point of applicative is that some things are applicative which aren't actually monads. |
| 14:47:41 | <lilac> | not many things, though... |
| 14:47:46 | <quicksilver> | no, not many at all :) |
| 14:48:30 | <Berengal> | ZipList |
| 14:48:45 | <lilac> | Berengal: got a second example? ;-) |
| 14:48:47 | <Berengal> | It's the only non-monad applicative I know of... |
| 14:49:10 | <Berengal> | Zip... maps? |
| 14:49:15 | <lilac> | hehe |
| 14:49:21 | <quicksilver> | ZipList is actually a monad. |
| 14:49:35 | <quicksilver> | just a different one to [] |
| 14:49:37 | <lilac> | quicksilver: you sure? |
| 14:49:45 | <quicksilver> | if you restrict to infinite streams |
| 14:49:48 | <quicksilver> | then diagonal is join |
| 14:49:56 | <lilac> | ah right, on infinite streams it's a monad |
| 14:50:01 | <lilac> | but not on finite ones |
| 14:50:08 | <quicksilver> | well it is, if they're fixed length |
| 14:50:15 | <quicksilver> | e.g. streams of length 8 |
| 14:50:23 | <quicksilver> | again, diagonal |
| 14:50:25 | <lilac> | that's also true, but that's a rather boring case of applicative |
| 14:50:25 | <quicksilver> | (I think) |
| 14:50:32 | <quicksilver> | ACTION shrugs |
| 14:50:37 | <Berengal> | Does that make arrays of a gievn size monads? |
| 14:50:44 | <Berengal> | given* |
| 14:50:45 | <quicksilver> | makes ZipList a bad example of an Applicative which isn't a monad, though. |
| 14:50:49 | <lilac> | any fixed structure F a built from a's is an applicative |
| 14:51:03 | <quicksilver> | Berengal: yes, same idea. |
| 14:51:11 | <quicksilver> | Berengal: given an array of arrays, take the diagonal |
| 14:51:22 | <lilac> | quicksilver: ZipList for finite lists is still a good example |
| 14:51:37 | <lilac> | (finite but not necessarily equally sized lists) |
| 14:51:40 | <quicksilver> | I think the applicative parsers is a good example. |
| 14:51:51 | <lilac> | aren't they usually monads too? |
| 14:51:54 | <quicksilver> | no |
| 14:52:01 | <quicksilver> | because that's the point |
| 14:52:10 | <quicksilver> | the applicative-ness lets you do first-letter optimisation |
| 14:52:17 | <quicksilver> | build parser tables as you go |
| 14:52:21 | <lilac> | i thought the point was, you could semantically make them monads, but you'd lose optimization opportunities |
| 14:52:28 | <quicksilver> | ACTION ponders |
| 14:52:34 | <lilac> | so in a sense they /are/ monads, but don't have a Monad instance |
| 14:52:42 | <quicksilver> | depends how you define them. |
| 14:52:51 | <quicksilver> | if you define them concretely with the first-letter tables visible |
| 14:52:56 | <quicksilver> | then there is no way to make them a monad |
| 14:53:10 | <Berengal> | lilac: Depends on if you want to pull their inner workings into the semantics... |
| 14:53:11 | <lilac> | ACTION ponders |
| 14:53:37 | <quicksilver> | data Parser a = ([Char],String -> (a,String)) |
| 14:53:43 | <jacobian> | I have a routine that as it searches also carries out some side computation as a result which is quite expensive and I want to keep. |
| 14:53:48 | <quicksilver> | or something. |
| 14:53:48 | <jacobian> | I want something like 'find' with type (a -> Maybe b) -> [a] -> Maybe b |
| 14:54:00 | <jacobian> | Does such a thing already exist? |
| 14:54:01 | <quicksilver> | the error applicative which collects multiple errors is another good one |
| 14:54:06 | <quicksilver> | (Which is not a monad) |
| 14:54:29 | <lilac> | quicksilver: data Parser a = Data.Map Char (Either (Maybe a) (Parser a))? |
| 14:54:54 | <quicksilver> | jacobian: head . catMaybes . map f |
| 14:55:03 | <quicksilver> | lilac: that kind of thing, yes. more than one way to do it. |
| 14:55:19 | <quicksilver> | jacobian: well, need a safe version of head. |
| 14:55:19 | <centrinia> | Is catMaybes similar to mappend? |
| 14:55:20 | <jacobian> | cool |
| 14:55:26 | <quicksilver> | msum . map f |
| 14:55:30 | <quicksilver> | that's better |
| 14:55:39 | <quicksilver> | > msum [Just 3, Just 4, Nothing, Just 5] |
| 14:55:40 | <lambdabot> | Just 3 |
| 14:55:41 | <doserj> | Compose f g in general, for applicatives f and g |
| 14:55:48 | <quicksilver> | > msum [Nothing, Just 3, Just 4, Nothing, Just 5] |
| 14:55:49 | <lambdabot> | Just 3 |
| 14:55:59 | <quicksilver> | msum is "first success" for a list of maybes. |
| 14:56:02 | <jacobian> | perfuct |
| 14:56:05 | <centrinia> | msum [Nothing] |
| 14:56:08 | <centrinia> | > msum [Nothing] |
| 14:56:09 | <lambdabot> | Nothing |
| 14:56:22 | <quicksilver> | doserj: sure, but that's only useful if you have a stock of other interesting applicatives to compose. |
| 14:56:43 | <doserj> | quicksilver: you have, any monad for example :) |
| 14:57:15 | <quicksilver> | well yes, but in many cases that does in fact lead to a monad again |
| 14:57:19 | <centrinia> | Is there a function ( \x -> case x of { Nothing -> []; Just x' -> [x'] } ) in the Prelude? |
| 14:57:25 | <quicksilver> | but agreed there are cases where it doesn't. |
| 14:57:30 | <lilac> | @type fmap (fmap msum) fmap :: (a -> Maybe b) -> [a] -> Maybe b |
| 14:57:31 | <quicksilver> | centrinia: maybeToList |
| 14:57:31 | <lambdabot> | forall a b. (a -> Maybe b) -> [a] -> Maybe b |
| 14:57:34 | <quicksilver> | @hoogle maybeToList |
| 14:57:35 | <lambdabot> | Data.Maybe maybeToList :: Maybe a -> [a] |
| 14:57:53 | <lilac> | @type (msum <$>) <$> fmap :: (a -> Maybe b) -> [a] -> Maybe b |
| 14:57:54 | <lambdabot> | forall a b. (a -> Maybe b) -> [a] -> Maybe b |
| 14:58:00 | <lilac> | @type (msum <$>) <$> (<$>) :: (a -> Maybe b) -> [a] -> Maybe b |
| 14:58:01 | <lambdabot> | forall a b. (a -> Maybe b) -> [a] -> Maybe b |
| 14:58:03 | <lilac> | yeah |
| 14:58:17 | <centrinia> | Okay, catMaybes = concatMap maybeToList ? |
| 14:58:24 | <lilac> | @src catMaybes |
| 14:58:25 | <lambdabot> | catMaybes ls = [x | Just x <- ls] |
| 14:58:28 | <fasta> | quicksilver: the module "illegal token" error in the haskell indent mode has not been corrected, btw. |
| 14:58:34 | <idnar> | @type concatMap maybeToList |
| 14:58:36 | <lambdabot> | forall b. [Maybe b] -> [b] |
| 14:58:54 | <lilac> | @check \x -> catMaybes x == concatMap maybeToList x |
| 14:58:55 | <lambdabot> | "OK, passed 500 tests." |
| 14:59:04 | <centrinia> | @type catMaybes |
| 14:59:05 | <lambdabot> | forall a. [Maybe a] -> [a] |
| 14:59:16 | <centrinia> | Their types are different. :( |
| 14:59:19 | <quicksilver> | fasta: send an email to kuribas. Or me :) |
| 14:59:49 | <lilac> | centrinia: hehe :) |
| 14:59:58 | <dev31212> | hi centrenia |
| 15:00:02 | <dev31212> | do any great good? |
| 15:00:12 | <centrinia> | dev31212, not yet. |
| 15:00:20 | <doserj> | quicksilver: I have a 2-line patch to make it work together with delete-selection-mode :) |
| 15:01:05 | <lilac> | dev31212: FOR GREAT JUSTICE! |
| 15:01:12 | <centrinia> | > bmi' 85 (5*12+7) -- I wonder if anyone cleared lambdabot's defined functions buffer. |
| 15:01:14 | <lambdabot> | Not in scope: `bmi'' |
| 15:01:19 | <quicksilver> | doserj: email that to kuribas too then :) |
| 15:01:49 | <fasta> | quicksilver: Are you this one btw? http://www.linkedin.com/pub/jules-bean/1/5b5/29a |
| 15:03:28 | <gwern> | @fact XMC |
| 15:03:28 | <lambdabot> | I know nothing about xmc |
| 15:06:50 | <lilac> | gwern: XMC! = XMC * (XMC - 1) * ... * 1 |
| 15:07:07 | <gwern> | lilac: lol? |
| 15:07:28 | <gwern> | anyways, I'm starting to suspect that the reason there's no happstack entry in the HCAR is because happs has never been in HCAR... |
| 15:09:11 | <gwern> | no wait. here's one, from 2007 |
| 15:11:29 | <gwern> | ...and only in 2007 |
| 15:11:39 | <gwern> | although it's interesting to look at the very first HCAR http://www.haskell.org/communities/11-2001/html/report.html |
| 15:11:47 | <gwern> | haskell has come a very long way in just 8 yearsz |
| 15:12:55 | <gwern> | for exmaple, where did all those dialects go? |
| 15:16:17 | <hackagebot> | hashed-storage 0.3 |
| 15:18:56 | <fasta> | gwern: a PhD lasts 4 years. 8 - 4 > 0 :) |
| 15:19:47 | <Beelsebob> | depends on the PhD |
| 15:19:54 | <Beelsebob> | some last 3 years, some never get finished |
| 15:19:58 | <pejo> | gwern, Concurrent Haskell is in GHC, isn't it? Phil Trinder has lots of research around GpH or similar projects. Björn Lisper's group is doing WCET analysis nowdays, O'Haskell is abandoned in favour of Timber, not sure about pH, Rita Loogen seems to still work on Eden, Generic Haskell.. is that one alive still? |
| 15:21:55 | <gwern> | fasta: yes, I suppose the cynical explanation is best |
| 15:22:27 | <gwern> | too bad, because I would've liked mobile haskell functionality - why *can't* we serialize computations and incidentally send parts of our programs over the network? |
| 15:22:28 | <quicksilver> | well for what ever reasons the ones that died didn't attract enough blood to stay alive |
| 15:22:39 | <quicksilver> | I was just about to say :) |
| 15:22:43 | <quicksilver> | GdH is probably the most surprising |
| 15:22:46 | <quicksilver> | of the casualties |
| 15:22:47 | <lars9> | hi, i'm using archlinux, which uses pacman as package manager. if i use cabal to install some package. will pacman conficts with cabal when installing the same package? such as haskell-x11 |
| 15:22:58 | <quicksilver> | I would have thought distribution was a pretty intersting topi. |
| 15:22:59 | <Peaker> | gwern: People have done this for Python, btw |
| 15:23:13 | <quicksilver> | people have done it for almost every language ever written |
| 15:23:14 | <gwern> | Peaker: well, being interpreted, I understand makes it easier |
| 15:23:21 | <Peaker> | gwern: Send lambdas over a network of powerful computers to compute and send back results |
| 15:23:52 | <quicksilver> | ACTION sends Peaker a lambda with a hacksaw hidden inside so he can escape from his computation factory. |
| 15:23:58 | <SamB> | Peaker: think I've heard about something like that in connection with Yhc ... |
| 15:24:21 | <gwern> | quicksilver: and it's hard to blame new blood for not showing up; it'd probably take me at least a year fulltime to get up to speed and start merging mobile haskell stuff into mainline ghc, and who's going to support me? |
| 15:24:35 | <Peaker> | Python makes it easier, having a serialized lambda form (bytecode) (except you're not allowed to use globals/etc in such a lambda, just the args) |
| 15:24:37 | <SamB> | does malcolmw know what I'm talking about ? |
| 15:24:49 | <SamB> | 'cause I sure don't |
| 15:25:06 | <malcolmw> | SamB: so what are you talking about? |
| 15:25:23 | <quicksilver> | mobile code for yhc |
| 15:25:25 | <SamB> | malcolmw: serializing lambdas over the network |
| 15:25:28 | <quicksilver> | is what he's trying to talk about. |
| 15:25:39 | <gwern> | SamB: yhc is like fusion - the compiler backend of the future |
| 15:25:54 | <quicksilver> | gwern: yeah, but how did it degrade this far? I'd have expected steady interest. |
| 15:26:00 | <SamB> | doesn't exist yet, you mean? |
| 15:26:05 | <lilac> | "the monomorphism restriction, when rendered in a system of inference rules, compromises the principal type property" |
| 15:26:05 | <quicksilver> | gwern: of course, in reality 0.1% of the community does 80% of the work, |
| 15:26:11 | <malcolmw> | Yes, Yhc can transmit its bytecodes over a network to be executed on another VM, with results being transmitted back. |
| 15:26:23 | <gwern> | SamB: it's the backend of the future, and always will be, is the joke I was going to |
| 15:26:35 | <quicksilver> | lilac: yes, and that's not all it breaks. |
| 15:26:43 | <quicksilver> | lilac: it breaks (one form of) eta expansion too. |
| 15:26:57 | <SamB> | not to mention my code |
| 15:27:01 | <gwern> | quicksilver: well, if there's a massive learning hump, and it's not obvious in advance it's going to die, then no new blood will show up in time |
| 15:27:23 | <quicksilver> | malcolmw: I didn't know that. |
| 15:27:28 | <fasta> | It has been done a number of times in the past already. It does not qualify as research anymore. |
| 15:27:36 | <quicksilver> | malcolmw: does all live data get carried over with it? |
| 15:27:37 | <SamB> | quicksilver: how is that possible when the community has only 610 members ? |
| 15:27:54 | <gwern> | SamB: I think haskell is bigger than 610 |
| 15:27:58 | <quicksilver> | SamB: for 0.39% of his time, JaffaCake does other things :P |
| 15:28:03 | <SamB> | hahaha |
| 15:28:07 | <quicksilver> | SamB: erm, 39%. |
| 15:29:54 | <malcolmw> | quicksilver: I don't recall the details. Basically, you can send a value containing unevaluated thunks over the wire, and the unevaluated bits get sent as bytecodes. When they are executed, they might refer to entities which are not present on the remote machine, so those get transferred later on demand. |
| 15:31:43 | <quicksilver> | malcolmw: ah, so the live data gets transferred on demand |
| 15:31:50 | <quicksilver> | malcolmw: in the terminology I was using. |
| 15:31:54 | <quicksilver> | that's interesting. |
| 15:32:51 | <doserj> | how does garbage collection work there? |
| 15:33:24 | <quicksilver> | doserj: a garbage truck drives from one machine to the other |
| 15:33:30 | <quicksilver> | doserj: once a week, on Thursdays. |
| 15:33:49 | <doserj> | :) |
| 15:34:03 | <doserj> | even on holidays? |
| 15:34:23 | <hatds> | ?instances Category |
| 15:34:25 | <lambdabot> | Couldn't find class `Category'. Try @instances-importing |
| 15:34:33 | <hatds> | ?instances Control.Category |
| 15:34:34 | <lambdabot> | Couldn't find class `Control.Category'. Try @instances-importing |
| 15:34:37 | <quicksilver> | if there a bank holiday, the major GC will be on Friday. |
| 15:34:47 | <quicksilver> | in cases of extended holidays, minor GCs will be arranged. |
| 15:35:16 | <jgriffin> | Hi there. I'm in the process of learning Haskell, but I need a bit of advice on which direction to take. I'm self-teaching, and I have experience programming prior to learning Haskell. If I read "Programming Haskell" and "Real World Haskell", will those two books alone be sufficient for teaching the language? Some suggest also reading Haskell: The Craft |
| 15:35:24 | <jgriffin> | of function programming, but is it necessary? |
| 15:35:44 | <quicksilver> | no. |
| 15:35:46 | <Peaker> | jgriffin: RWH should be enough, as far as I heard. I haven't heard of Programming Haskell |
| 15:35:52 | <quicksilver> | many people learn by reading no books at all. |
| 15:35:55 | <hatds> | ?instances Arrow |
| 15:35:56 | <lambdabot> | (->), Kleisli m |
| 15:35:59 | <quicksilver> | the two you mention are both good books. |
| 15:36:12 | <quicksilver> | Of course, all the authors visit this channel, so I have to say that :) |
| 15:36:14 | <Peaker> | jgriffin: I learned Haskell by experimenting with it, reading some tutorials on the web, and hanging out in #haskell |
| 15:36:22 | <aledge> | RWH is really good, you should be fine if you have prior experience. You'll learn the most by trying to code something, of course |
| 15:36:41 | <quicksilver> | I believe Hutton's book is good but aimed at undergraduate students |
| 15:36:50 | <quicksilver> | whilst RWH is aimed more at programmers wanting to code |
| 15:37:04 | <jgriffin> | Peaker: I've actually found that I retain the information best when I code myself, not when I read what others have written. I agree. :D |
| 15:37:18 | <smarmy> | i'd at least read RWH. yes, you can learn yourself, but like any subject, you miss a lot of the small insights that someone with experience can convey to you earlier than later |
| 15:37:26 | <jgriffin> | right |
| 15:37:29 | <jgriffin> | Okay then. |
| 15:37:44 | <jgriffin> | Thanks guys. |
| 15:37:45 | <hatds> | you should watch "A Taste of Haskell" |
| 15:37:51 | <hatds> | very good first pass of the language |
| 15:38:20 | <jgriffin> | hatds: I'll check it out. |
| 15:48:14 | <Cale> | jgriffin: It also might be worth pointing out |
| 15:48:15 | <lambdabot> | Cale: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 15:48:18 | <Cale> | @where lyah |
| 15:48:19 | <lambdabot> | www.learnyouahaskell.com |
| 15:48:27 | <Cale> | which looks fun :) |
| 15:48:45 | <Cale> | I think most people end up using a mishmash of sources :) |
| 15:49:17 | <jgriffin> | I'm kind of getting that vibe... |
| 15:49:18 | <Cale> | jgriffin: and ask lots of questions here :) |
| 15:49:43 | <jgriffin> | I like this channel. The people don't bite too frequently... |
| 15:49:48 | <TomMD> | Grrrr |
| 15:49:54 | <Cale> | We are the documentation. :) |
| 15:50:35 | <dev31212> | learnyouahaskell is the first site where I started to feel like I knew what I was doing :) |
| 15:50:38 | <dev31212> | great site... |
| 15:50:43 | <Athas> | Just out of curiosity, but are the GHC hackers still going to switch away from Darcs? |
| 15:50:44 | <dev31212> | moved on since, of course |
| 15:51:26 | <TomMD> | Athas: They were talking in #ghc ten minutes ago, you could ask them. |
| 15:51:42 | <shapr> | I want to build GHC with eight cores and 16GB of ram, are there any command line options I can change to take advantage of the extra resources? |
| 15:52:06 | <dev31212> | what a beast machine. |
| 15:52:16 | <jgriffin> | dev31212: I think I'm past the point of "Learn you a Haskell". I've already absorbed the first half of Programming Haskell, and it looks like I've covered what goes on in that tutorial. |
| 15:52:17 | <TomMD> | shapr: Couldn't you use -j5? |
| 15:52:25 | <TomMD> | or -j9 |
| 15:52:29 | <dev31212> | jgriffan, cool |
| 15:52:34 | <shapr> | TomMD: I'm using -j10, but that won't use more memory, right? |
| 15:52:38 | <Cale> | jgriffin: Ah, okay :) |
| 15:52:41 | <CosmicRay> | still trying to work around the API change in time in convertible. MIN_VERSION_time() doesn't work because it only matches the first three bits of the version number |
| 15:52:50 | <CosmicRay> | how else might I do it? |
| 15:52:53 | <TomMD> | shapr: No more than needed - it won't do cool caching. |
| 15:52:56 | <dev31212> | Real World Haskell...And the wikibooks book on Haskell are what I am on at the moment |
| 15:53:06 | <dev31212> | Well Im half way through Real World Haskell |
| 15:53:21 | <shapr> | I'm pretty sure GHC can build faster if each GHC compile is given more heap or something. |
| 15:53:23 | <TomMD> | And how many worlds have you realized? |
| 15:53:37 | <dev31212> | I have realized the Monadic world |
| 15:53:42 | <dev31212> | where the universe is just one object |
| 15:53:45 | <dev31212> | I have seen past |
| 15:53:48 | <dev31212> | present and future at once |
| 15:53:53 | <dev31212> | Like The Quizat Kadderach |
| 15:54:33 | <hackagebot> | convertible 1.0.3 |
| 15:55:23 | <CosmicRay> | damn, that was fast |
| 15:55:32 | <Baughn> | conal: I realized there's a bit of a semantic problem with my implementation of makeEvent - namely, the next occurence. It's not known when (or even if) it'll happen, but it /is/ known that it won't happen before the current time, which I ought to take advantage of - otherwise, merging the event with another would be impossible, never mind joining it |
| 15:55:36 | <mornfall> | dev31212: How much for that stuff you are smoking? ; - ) |
| 15:56:07 | <Baughn> | conal: I have a suspicion you already fixed this at some point in the past, though. (And also that it involves improving values). Any thoughts? |
| 15:56:40 | <dev31212> | mornfall, $42 :) |
| 15:56:52 | <quicksilver> | Baughn: that's the key problem of making "joinE" efficient, yes |
| 15:57:00 | <quicksilver> | Baughn: "observing information about non-occurrence" |
| 15:57:22 | <quicksilver> | Baughn: it's actually not required to make it semantically possible, but if you can't observe and remember non-occurrence you waste a lot of time cheking for it |
| 15:59:17 | <Baughn> | quicksilver: When it comes to events whose next occurence, if any, is driven by an IO sink instead of being computed some other way? |
| 16:00:18 | <quicksilver> | Baughn: well in some sense your implementation has to cope with all four permutations |
| 16:00:42 | <quicksilver> | Baughn: IOsink / IOsink, IOsink / purely computed, etc. |
| 16:00:45 | <quicksilver> | hmm. 3 permutations ;) |
| 16:01:00 | <BioHazardSoftwar> | Hey everyone |
| 16:01:04 | <Baughn> | quicksilver: I'd use a special Time type |
| 16:01:10 | <quicksilver> | one place where I disagree with conal's implementation is the amount of stuff working directly on events. |
| 16:01:16 | <quicksilver> | I believe it makes more sense to define most primitives on futures |
| 16:01:42 | <Baughn> | quicksilver: Whose exact value can't be checked without waiting for the event to occur (or the finalizer to trigger and cap it), but can be checked for inequality using unsafePerformIO to read the clock |
| 16:02:46 | <Baughn> | ACTION sighs |
| 16:03:07 | <quicksilver> | well my preference is not to use unsafePerformIO to hide things away like that |
| 16:03:10 | <quicksilver> | but we'll see. |
| 16:03:13 | <Baughn> | ..it might be simpler to try implementing reactive from scratch, for learning to understand this. The existing code is.. convoluted, and I don't really understand why |
| 16:03:22 | <quicksilver> | my approach may fail to yield an efficient implementation. |
| 16:03:43 | <hatds> | is there a simple reactive example available that represents a runnable, interactive program with stdin? |
| 16:04:06 | <Baughn> | I've got a couple |
| 16:04:08 | <Baughn> | Let me see.. |
| 16:05:16 | <conal> | Baughn: yeah. i have dealt with this issue. it's *very* important. |
| 16:05:16 | <lambdabot> | conal: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 16:06:36 | <hackagebot> | Hieroglyph 2.24 |
| 16:06:38 | <Baughn> | hatds: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5376#a5376 <-- OKay, I guess this is about the minimal one |
| 16:06:57 | <conal> | Baughn: you've run into all of the awkward spots i know of in reactive: external input, correct unamb implementation, and event join. |
| 16:07:10 | <Baughn> | conal: Right. Obviously my current makeEvent doesn't handle it, but I did at least figure out how to get the finalizers working right |
| 16:07:21 | <hatds> | can you put in the imports for me? |
| 16:07:24 | <Baughn> | conal: So if you've already dealt with it, I'm hoping you can adapt it. :) |
| 16:07:34 | <conal> | Baughn: i'll look |
| 16:08:08 | <Baughn> | hatds: ..I'm not really sure what they are. Umh.. LegacyAdapters, Control.Applicative.. yeah, I think it's just those two. |
| 16:08:50 | <Baughn> | conal: If I've run into all of them, it's because I started deliberately looking for bugs. :P |
| 16:09:19 | <hatds> | is Reactive not really runnable then? |
| 16:10:15 | <Baughn> | hatds: Well, there are enough bugs that you're pretty much bound to run into them. I'm smacking them as fast as I can, but since that involves figuring out conal's code at the same time.. |
| 16:10:44 | <Baughn> | hatds: I may be introducing new ones too. Like the makeEvent/mappend bug I just figured out I'd caused. :P |
| 16:11:24 | <LeCamarade> | Baughn, When I run a program in runhaskell, to what level does it get compiled? |
| 16:11:34 | <Baughn> | LeCamarade: Not at all. |
| 16:11:44 | <LeCamarade> | Ah. |
| 16:11:50 | <Baughn> | Well, it's compiled to bytecode; ghci/hugs aren't pure interpreters. |
| 16:11:56 | <LeCamarade> | Hence the variation! |
| 16:13:05 | <LeCamarade> | It's so surprising. There is that deadlock I told you about, and it never ever shows up when I runhaskell. But once I get the code compile, it is consistent. And I just can't trace it. (I really want to know why I'm getting it, but I may never.) |
| 16:13:32 | <conal> | LeCamarade: multi-threaded code? |
| 16:13:48 | <conal> | i think ghci runs as if linked with -threaded. |
| 16:13:57 | <Cale> | Yeah... try with -threaded |
| 16:14:07 | <Cale> | I had some strange problems like that too |
| 16:14:37 | <Cale> | It seems that some C library bindings don't work very well without -threaded |
| 16:15:43 | <conal> | i think C calls block the RTS unless -threaded |
| 16:16:27 | <conal> | ksf: poing |
| 16:16:33 | <conal> | ksf: i mean "ping" |
| 16:17:19 | <bos31337_> | pyongyang |
| 16:17:40 | <conal> | pyin/pyang |
| 16:17:56 | <aledge> | pinyin? |
| 16:19:04 | <heatsink> | If you're going to make many data types have the same field, how would you do that? |
| 16:19:31 | <heatsink> | I can think of adding the field to each constructor and defining a class HasField a where getField :: a -> Field; setField :: Field -> a -> a |
| 16:19:57 | <heatsink> | Or creating a wrapper data type, data WithField a = WithField Field a |
| 16:20:34 | <lars9> | :t id |
| 16:20:35 | <heatsink> | The latter makes pattern matching slightly more convenient, but I think the former may be easier to maintain |
| 16:20:35 | <lambdabot> | forall a. a -> a |
| 16:20:44 | <lars9> | @src id |
| 16:20:44 | <lambdabot> | id x = x |
| 16:21:59 | <heatsink> | Has anyone here seen an idiom for this in an existing project? |
| 16:22:04 | <lars9> | :t pure id <*> v |
| 16:22:05 | <lambdabot> | Couldn't match expected type `f a' against inferred type `Expr' |
| 16:22:05 | <lambdabot> | In the second argument of `(<*>)', namely `v' |
| 16:22:05 | <lambdabot> | In the expression: pure id <*> v |
| 16:22:20 | <lars9> | :t pure id <*> (*2) |
| 16:22:22 | <lambdabot> | forall a. (Num a) => a -> a |
| 16:22:29 | <lars9> | :t pure id <*> |
| 16:22:30 | <lambdabot> | parse error (possibly incorrect indentation) |
| 16:22:41 | <lars9> | :t ( pure id <*> ) |
| 16:22:42 | <lambdabot> | forall a (f :: * -> *). (Applicative f) => f a -> f a |
| 16:22:50 | <glguy> | :t (id <$> ) |
| 16:22:52 | <lambdabot> | forall a (f :: * -> *). (Functor f) => f a -> f a |
| 16:23:20 | <lars9> | :t ( pure id ) |
| 16:23:21 | <lambdabot> | forall a (f :: * -> *). (Applicative f) => f (a -> a) |
| 16:23:38 | <quicksilver> | lars9: lambdabot replies to private messages. |
| 16:23:45 | <quicksilver> | lars9: also you can install GHCi on your own machine :) |
| 16:24:00 | <quicksilver> | lars9: the purpose of lamdabot in a public channel is to form part of an ongoing discussion ;) |
| 16:24:06 | <lilac> | heatsink: i vaguely recall a GHC extension where field names could be reused across multiple 'data' |
| 16:24:13 | <quicksilver> | heatsink: I've see variations of both of those. |
| 16:24:31 | <quicksilver> | heatsink: in the very very rare case where I want that, I favour the class HasField approach. |
| 16:24:46 | <quicksilver> | but I don't find the idiom that useful. |
| 16:24:53 | <lilac> | heatsink: do you want to be able to treat such things polymorphically? |
| 16:24:57 | <quicksilver> | (there is often a more useful class or HOF to use than HasField) |
| 16:25:20 | <lilac> | (are there any higher-level operations you wish to perform over all such data types?) |
| 16:25:37 | <LeCamarade> | conal, Yes, multithreaded. |
| 16:25:41 | <hackagebot> | checkers 0.2 |
| 16:25:55 | <lilac> | heatsink: does this field have the same type for all datatypes? does the datatype make sense if you remove the field? |
| 16:26:48 | <heatsink> | lilac: I don't expect to do any interesting HOFs over such data types. They make sense without the field. |
| 16:27:20 | <heatsink> | lilac: In my case, the extra field is information about the source of a data structure that was produced from an input file. |
| 16:28:01 | <heatsink> | If it were removed, you could still do everything except report source line information together with the output. |
| 16:28:54 | <Cale> | heatsink: Maybe separate it into another type? |
| 16:29:13 | <Cale> | I don't know how inconvenient that would be... |
| 16:29:34 | <lilac> | heatsink: ... yeah, what Cale said :) |
| 16:29:38 | <heatsink> | Cale: what do you mean? Source information is another type, but it has to be attached to other data types somehow. |
| 16:30:07 | <lilac> | heatsink: data WithSourceInformation a = WSI { sourceInformation :: SourceInformation, body :: a } |
| 16:30:25 | <lars9> | what's the applicative functor in "pure id <*> (+2)" |
| 16:30:33 | <lilac> | lars9: reader |
| 16:30:45 | <heatsink> | That was one of my two proposals, above: data WithField a = WithField Field a |
| 16:30:57 | <Cale> | ah, okay |
| 16:30:59 | <Cale> | I missed that |
| 16:32:54 | <heatsink> | I guess the two things that I don't like about that are that it's not composable and that it introduces extra levels of indirection. |
| 16:33:17 | <heatsink> | What I mean about composability is, suppose I had two bits of extra information: source position and user annotations. |
| 16:33:33 | <heatsink> | Now WithSourceInformation (WithUserAnnotations a) /= WithUserAnnotations (WithSourceInformation a) |
| 16:34:17 | <mmorrow> | so it's not commutative |
| 16:34:42 | <lilac> | lars9: you can tell it's the reader monad because <*> takes an Appliactive on both sides and the RHS is a function |
| 16:34:47 | <heatsink> | Right. |
| 16:34:53 | <Saizan_> | you could implement extensible records in ghc |
| 16:34:56 | <Saizan_> | or use HList |
| 16:34:58 | <heatsink> | With type classes, you'd have (HasSourceInformation a, HasUserAnnotations a) => a |
| 16:35:02 | <Cale> | One thing you could do is just include the fields with a Maybe type. |
| 16:35:17 | <Cale> | But that's perhaps a little less typesafe |
| 16:35:27 | <heatsink> | Which is "commutative" in the sense that type class constraints are unordered. |
| 16:35:43 | <lilac> | lars9: incidentally, pure f <*> x = f <$> x = fmap f x, so pure id <*> x = fmap id x = x |
| 16:36:59 | <Cale> | (In the sense that whether the fields are present or not is a runtime property then.) |
| 16:37:07 | <heatsink> | right |
| 16:37:41 | <lilac> | lars9: (the first equality comes from the Applicative laws, the second from the Functor laws) |
| 16:38:26 | <Cale> | You can also have your datatype (assuming it's recursive, or else this is kind of silly) take an extra arbitrary type parameter for all the extra information that it's annotated with. |
| 16:38:35 | <Athas> | How do people use Parsec nowadays? Through an applicative functor interface? |
| 16:38:43 | <lars9> | lilac: where is <$> defined? not defed in control.applicative and control.monad |
| 16:38:45 | <Cale> | and then just construct a big enough type for all the annotations you want to make |
| 16:38:55 | <Cale> | Athas: and monadically |
| 16:39:08 | <Beelsebob> | lars9: Control.Applicative |
| 16:39:14 | <Cale> | Athas: Applicative notation is convenient sometimes though. |
| 16:39:30 | <lilac> | @index (<$>) |
| 16:39:30 | <lambdabot> | bzzt |
| 16:39:52 | <Athas> | Cale: yes, I noticed. But it looks like it can easily become unreadable if used indiscriminately as well. |
| 16:40:08 | <heatsink> | Cale: That's true, but since the code statically knows what annotations are there, I think that's kind of overkill. |
| 16:40:42 | <lilac> | quicksilver: (thinking back to applicative parsers), you could still make a monad instance assuming your parser is pure, by trying it on all possible first letters |
| 16:41:29 | <Cale> | heatsink: Well, the type that you apply it at can be different in different parts of the code then |
| 16:42:10 | <heatsink> | Cale: Yeah, I do that when the type changes in different parts of the code :) |
| 16:45:08 | <heatsink> | In my experience, overusing type variables can lead to having to insert/remove type variables in lots of signatures, even when there's no change to the code. |
| 16:45:45 | <heatsink> | And not solving the field problem I was asking about can lead to having to insert/remove underscores in lots of patterns, even when there's no real change to the code. |
| 16:46:12 | <Cale> | Well, that's what the record syntax is primarily for... |
| 16:46:26 | <Cale> | (not having to insert/remove underscores in patterns) |
| 16:46:44 | <heatsink> | oh yeah |
| 16:46:50 | <heatsink> | I forgot about that |
| 16:47:15 | <heatsink> | So that's what Saizan_ meant about extensible records |
| 16:47:29 | <Cale> | Actually, probably not :) |
| 16:47:34 | <ray> | record syntax is pretty useful, but i feel like i have to take a shower every time i use it |
| 16:47:39 | <Cale> | Extensible records are something that Haskell doesn't have |
| 16:47:46 | <Cale> | But would make your life much easier |
| 16:49:24 | <Cale> | Basically, it gives you a particular new kind of record type with labelled/typed fields, and a way to write functions which are polymorphic over any record that has certain fields |
| 16:50:45 | <heatsink> | I see |
| 16:50:57 | <quicksilver> | lilac: well really it's first-token not first-letter |
| 16:51:10 | <quicksilver> | lilac: and if the intention was for it to be 0-lookahead then you can't do that. |
| 16:51:29 | <quicksilver> | lilac: you can make the monad instance by backtracking, which breaks the idea of the parser, yes. |
| 16:51:58 | <Cale> | (and polymorphically extend any record with additional fields) |
| 16:58:05 | <nibro> | Cale: depends on what you mean by Haskell - there's TRex for hugs |
| 16:58:18 | <Berengal> | Cale: Sort of like creating a type class for each accessor function? |
| 17:01:44 | <Cale> | nibro: That's true |
| 17:01:58 | <heatsink> | Well, I feel better about going with the type class solution then :) |
| 17:02:53 | <quicksilver> | Berengal: well, some record typing systems allow upper as well as lower bounds on the fields |
| 17:03:02 | <quicksilver> | IIRC ocamls' extensible variants has this |
| 17:03:05 | <quicksilver> | <: and :> |
| 17:03:14 | <quicksilver> | that would not be easy to express with typeclasses |
| 17:03:21 | <quicksilver> | TCs are not good at negative information. |
| 17:03:30 | <quicksilver> | due to being open. |
| 17:03:35 | <quicksilver> | hence all the hoops oleg builds around HFalse |
| 17:06:24 | <Cale> | With sufficiently complicated typeclasses, you can approximate it, and some libraries, like HaskellDB, actually do this |
| 17:06:50 | <Cale> | But it's something which would really be a lot nicer if you didn't have to use typeclasses to do it. |
| 17:07:28 | <Cale> | Oh, that was in reference to extensible records, though I suppose with extensible variants it also somewhat applies |
| 17:07:55 | <Cale> | You can use existentials and typeclasses to approximate extensible variants, like the new exceptions library does |
| 17:08:04 | <Cale> | But again, not the prettiest result. |
| 17:08:58 | <quicksilver> | Cale: but on the other hand, true extensible variants break the type system pretty badly |
| 17:09:03 | <quicksilver> | Cale: so maybe it's not abad thing we can't do it. |
| 17:10:59 | <Cale> | quicksilver: Oh? How so? |
| 17:11:20 | <Cale> | I think it's possible to do true extensible variants without breaking the type system. |
| 17:12:15 | <quicksilver> | Cale: well FSOV of "breaking" |
| 17:12:25 | <quicksilver> | Cale: you get something not remotely as pleasant as we have now. |
| 17:12:39 | <quicksilver> | Cale: in particular with the subtype/supertype polymorphism |
| 17:13:25 | <quicksilver> | that's the <: and :> stuff |
| 17:13:30 | <quicksilver> | I can't remember the details, alas. |
| 17:14:40 | <Cale> | As long as you confine subtyping/supertyping to the kind of variants, then I think it should be okay. |
| 17:16:09 | <Cale> | Well, what you really want is more or less a row variable of possible labels/types for the variant. So it's almost identical to the extensible record system. |
| 17:17:58 | <hackagebot> | haskeline 0.6.1.6 |
| 17:35:45 | <ksf> | conal, pong |
| 17:42:48 | <jeffersonheard> | crud... is wouter swierstra on here? |
| 17:47:54 | <conal> | ksf: hi. i see you ran into trouble with quickcheck versions. |
| 17:49:21 | <conal> | ksf: i've pushed a new checkers. will push other libs as well. |
| 17:49:59 | <conal> | jeffersonheard: i think so. anyone remember wouter's irc handle? |
| 17:50:03 | <ksf> | conal, yes, C calls block, even when threaded, at least that's my best guess from how stuff behaves, I never wrote a test or something to pin the semantics down. |
| 17:50:43 | <ksf> | cabal update |
| 17:50:45 | <ksf> | grr. |
| 17:53:41 | <ksf> | conal, still, I'd like to have ifdef's around all test code, just to calm my engineering intuition after hitting upon that BinOp thing. |
| 17:54:00 | <ksf> | production code depending on test cases freaks me out. |
| 17:55:09 | <conal> | ksf: ifdefs around Arbitrary & CoArbitrary instances? |
| 17:56:04 | <ksf> | yes, around those, around the quickcheck imports, and the rest of the test case, so that you can build a version of reactive without tests enabled, and not depending on quickcheck, at all. |
| 17:58:38 | <conal> | ksf: does that desire come from a general wish to reduce package dependencies where possible? or maybe something more specific to quickcheck or checkers? |
| 17:59:23 | <ksf> | uhhh... both. |
| 17:59:26 | <conal> | ksf: what's the BinOp thing? |
| 18:00:43 | <ksf> | merge in PrimReactive uses BinOp, and it's used in a thousand instances that don't look like tests. It's out of checkers afair. |
| 18:01:34 | <conal> | ksf: oh, i see. yeah. BinOp has nothing do with testing, so it's not logical for me to get it from checkers. |
| 18:01:37 | <ksf> | ...or, rather it's used in the Monoid Event instance, and that's used all over the place. |
| 18:02:05 | <conal> | ksf: i don't know how to manage *not* including QC instances in my libraries. other libraries & apps will need them. |
| 18:02:15 | <conal> | ksf: i.e., they're not just for testing *my* libs. |
| 18:02:44 | <conal> | i want all libs that i use to define & export QC instances. and i expect others will want the same from me. |
| 18:02:44 | <ksf> | well, if someone wants to run tests, they can compile with --enable-testing |
| 18:03:11 | <conal> | ksf: that's a separate issue, don't you think? |
| 18:03:32 | <conal> | and sure, for running my tests, --enable-testing would be fine. |
| 18:03:52 | <conal> | btw, is --enable-testing a standard flag or one i'd define in my .cabal files? |
| 18:04:08 | <ksf> | well, I think that test and production code should be sharply seperated, and ifdef's are the best way to ensure that, even if noone ever compiles without tests enabled. |
| 18:04:43 | <ksf> | dunno, I didn't look at how to integrate with cabal, yet. |
| 18:05:18 | <dcoutts> | conal: right, you can't (or at least should not) conditionally export stuff |
| 18:05:21 | <kynky> | ksf, ideal world vs real world (there are always side effects) |
| 18:05:25 | <ksf> | it probably should be a standard flag, though, like enable docs. |
| 18:05:41 | <dcoutts> | ksf: the difference is that docs do not affect the exported API |
| 18:06:02 | <dcoutts> | cabal flags are not supposed to affect the exported API |
| 18:06:27 | <dcoutts> | dependency planning relies on that, and there's deliberately no way to express a dependency on a package built with some set of flags |
| 18:07:01 | <dcoutts> | also such conditional package building does not translate into binary distro packages |
| 18:08:38 | <Berengal> | An alternative is to break a package in two, foo and foo-tests |
| 18:09:39 | <dcoutts> | I think it's better just to depend on QC |
| 18:10:01 | <conal> | Berengal: or even three: foo, foo-QC (with QC instances), and foo-tests |
| 18:10:01 | <dcoutts> | we'll soon get to the stage where we've got a sensible QC version as standard |
| 18:10:25 | <conal> | dcoutts: yeah. it's an awkward moment w.r.t QC now. |
| 18:10:32 | <conal> | transitional |
| 18:10:36 | <dcoutts> | problem is that the release of ghc-6.10 and QC2 happened at almost the same time |
| 18:10:44 | <dcoutts> | so ghc-6.10 shipped QC 1.2 |
| 18:10:52 | <dcoutts> | and the platform had to follow that |
| 18:11:09 | <dcoutts> | but the next major release will undoubtedly update to QC2 |
| 18:11:35 | <conal> | i was surprised at how much work it took me to change checkers over from QC1 to QC2. some pretty big changes. |
| 18:17:57 | <ksf> | ACTION stays stubborn and still reserves the right to write #ifndef ENABLE_TESTS around code and nag about things like BinOp |
| 18:19:15 | <conal> | ksf: to eliminate a QC dependency? |
| 18:20:02 | <ksf> | well, that's just a nice side-effect of being a nazi about minimal dependencies. |
| 18:20:29 | <conal> | ksf: i could split reactive into two or three packages. |
| 18:20:42 | <conal> | ksf: since the exports would differ |
| 18:21:05 | <conal> | ksf: although it depends on other package(s) that depend on QC |
| 18:21:17 | <ksf> | don't you need to tests non-exported functions? |
| 18:21:48 | <conal> | ksf: and representation. it'd be painful and ultimately unsatisfactory. |
| 18:22:20 | <dcoutts> | conal: I'd just stick to depending on QC, it's not a heavy dep, it's just the current issue of the transition |
| 18:22:33 | <conal> | ksf: and if i don't split the package, i can't support libs that build on top of reactive |
| 18:22:44 | <ksf> | I still don't understand why changing exports would be bad, but I've missed some of the discussion due to my network. |
| 18:22:48 | <conal> | ksf: i mean if i don't somehow provide dependable QC instances for reactive types. |
| 18:23:02 | <ksf> | otoh, the tests exports could just be calls to errors. |
| 18:24:07 | <conal> | dcoutts keeping QC dependence is my leaning as well. however, i want to hear ksf out. i figure he wouldn't be complaining if he didn't have a good reason in there somewhere. |
| 18:24:21 | <dcoutts> | ksf: the problem is that conditional exports breaks package management |
| 18:24:22 | <dcoutts> | conal: sure |
| 18:24:41 | <ksf> | the reason is BinOp, and catching such things. |
| 18:24:53 | <kynky> | maybe package management could be cleverer |
| 18:25:04 | <Baughn> | conal: Yep, figured out another problem with unamb. This one is relatively obscure, depending on the exact behavior of the caller.. you can thank Dupree for making me think about it. :P |
| 18:25:26 | <Baughn> | As a plus, the solution should also make unamb cleaner |
| 18:25:36 | <dcoutts> | kynky: it's a bit hard to change the distro package management systems |
| 18:25:38 | <conal> | Baughn: great! thanks Dupree! |
| 18:25:50 | <dcoutts> | kynky: just changing our own is not enough |
| 18:25:52 | <ksf> | so, in the end, it doesn't matter if reactive can be cabal-installed without test code, as long as you can complie it without tests during development, to check if stuff's in the right place. |
| 18:26:40 | <conal> | ksf: i don't even know how to define "in the right place" in such a way that i'd know BinOp wasn't. help? |
| 18:26:44 | <kynky> | gentoo package management is pretty flexible now, but some others are archaic i guess |
| 18:27:31 | <ksf> | well, checkers is a test library, and whole reactive depends on it in a crucial way, not just the tests. |
| 18:28:03 | <ksf> | I figure it should be in a package both checkers and reactive depend upon. |
| 18:28:22 | <conal> | ksf: yeah. or duplicated. |
| 18:28:28 | <ksf> | or that, yes. |
| 18:28:41 | <conal> | type UnOp a = a -> a |
| 18:28:53 | <conal> | i never know what to do with such trivial but widely useful things |
| 18:29:08 | <ksf> | Prelude.Conal? |
| 18:30:34 | <ksf> | actually, it'd be nice to have a collection of Prelude.*s, just to have a library of different coding styles, and a repository to draw from to extend the prelude. |
| 18:32:07 | <Berengal> | ksf: I actually like that idea... |
| 18:32:22 | <conal> | ksf: i can deal with UnOp/BinOp one way or another. also tests. that leaves testing functionality, which still has to get exported. don't know what to do there. |
| 18:32:31 | <dcoutts> | kynky: right, the binary ones are more restrictive |
| 18:33:12 | <ksf> | conal, don't worry. |
| 18:33:29 | <conal> | ksf: where testing functionality includes QC instances and other reusable support. |
| 18:35:44 | <ksf> | I'm going to write those defines, and leave you alone if it compiles with the test dependencies removed, I don't really care about really _installing_ a test-less reactive. |
| 18:36:15 | <sayyestolife> | what are some good mailing lists that one should subscribe to? (except the haskell ones, already got them!) |
| 18:36:26 | <ksf> | regard them as another test case, testing the independency of code from tests. |
| 18:40:05 | <Berengal> | Hmmm, splitting packages does make it hard to test unexported functions, ifdefs are ugly and complicate dependencies, and putting the tests in the same package as the code doesn't /really/ make sense; couldn't match expected type Code against inferred type Test in the expression 'testModule : package' |
| 18:41:56 | <Berengal> | If you were somehow able to give a package full access to all modules (perhaps even private declarations) in another package, splitting wouldn't be so bad |
| 18:44:42 | <ksf> | Berengal, you'd have to recompile the package you depend on, due to inlining and stuff. |
| 18:45:12 | <Berengal> | ksf: Yes, I realize that. This is the "somehow" part in my previous statement |
| 18:45:37 | <Berengal> | Somehow == magic, usually |
| 18:46:11 | <kynky> | === |
| 18:46:39 | <ksf> | #ifndef DISABLE_TESTS isn't ugly, but useful documentation. |
| 18:46:59 | <Berengal> | ksf: It mixes tests and code in files |
| 18:47:37 | <ksf> | yeah, but you won't get your full-access cake, ever, without recompiling. |
| 18:47:44 | <Berengal> | They might be separate at compile time, but to me it's more important that they're separate in the source as well |
| 18:48:29 | <ksf> | file-based structuring is overrated. |
| 18:48:51 | <ksf> | I know, I once failed an exercise because I didn't split up 200 lines of C into 4 files. |
| 18:49:00 | <kynky> | just a hierarchy, simple rules though |
| 18:50:57 | <Berengal> | ksf: I once handed in a java assignment consisting of n files of n ±2 lines each |
| 18:51:30 | <ksf> | yay there's a reason that there are inner classes. |
| 18:51:31 | <Berengal> | So I agree that it's overrated. Tests don't belong in the same code they're testing though |
| 18:52:11 | <kynky> | Berengal, agreed |
| 18:52:36 | <kynky> | or stuff that is only used by tests |
| 18:52:41 | <Berengal> | To me the reason why is similar enough to why we use exceptions instead of return values and nested ifs |
| 18:52:54 | <ksf> | hmmm. I would agree on "tests testing the api don't belong in the code they're testing" |
| 19:00:52 | <rubendv> | I get an occurs check error on the definition of >>= here: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2522 |
| 19:01:01 | <rubendv> | Anyone knows what I'm doing wrong? |
| 19:01:12 | <ksf> | you're defining a recursive type. |
| 19:01:34 | <ksf> | usually, that's an error, if it's not, you still need a newtype or data declaration to get it past the type checker. |
| 19:01:50 | <rubendv> | Yes, but I don't see how it is recursive? |
| 19:02:13 | <byorgey> | what? how is rubendv defining a recursive type? |
| 19:02:43 | <rubendv> | Occurs check: cannot construct the infinite type: a = structure a |
| 19:02:45 | <rubendv> | is what I get |
| 19:02:53 | <byorgey> | rubendv: well, let's see, what's the type of >>= ? |
| 19:02:57 | <byorgey> | @type (>>=) |
| 19:02:59 | <lambdabot> | forall (m :: * -> *) a b. (Monad m) => m a -> (a -> m b) -> m b |
| 19:03:13 | <byorgey> | so here, m = (Chat structure) |
| 19:03:32 | <byorgey> | so it should be of type Chat structure a -> (a -> Chat structure b) -> Chat structure b |
| 19:03:57 | <byorgey> | rubendv: so if you have (Chat ms) >>= f, what is the type of ms? |
| 19:04:04 | <byorgey> | and what is the type of f? |
| 19:04:22 | <rubendv> | ms :: (structure a) |
| 19:04:27 | <byorgey> | right |
| 19:05:06 | <rubendv> | oh and a itself has to be a structure too |
| 19:05:10 | <rubendv> | I se |
| 19:05:12 | <rubendv> | *see |
| 19:05:30 | <byorgey> | why would a have to be a structure too? |
| 19:05:57 | <rubendv> | because f is applied to something of type (structure a) |
| 19:06:04 | <byorgey> | ok, right. |
| 19:06:39 | <byorgey> | you can't directly apply a function a -> Chat structure b to a (structure a). |
| 19:07:01 | <byorgey> | if you use fmap you can get a (structure (Chat structure b)) |
| 19:07:18 | <byorgey> | which is really just a (structure (structure b)) (after removing the 'Chat' constructor) |
| 19:07:25 | <byorgey> | and then you can use join to turn that into a (structure b). |
| 19:07:39 | <rubendv> | o_O |
| 19:07:51 | <rubendv> | okay let me think on that for a while :p |
| 19:08:13 | <rubendv> | Well it isn't really necessary for it to be a monad |
| 19:08:37 | <byorgey> | it isn't necessary for what to be a monad? Chat? |
| 19:08:40 | <rubendv> | I wanted it to be an instance of a class like Monoid or MonadPlus |
| 19:08:42 | <rubendv> | yes |
| 19:08:53 | <rubendv> | but Monoid needs things of kind * |
| 19:09:10 | <rubendv> | so I thought MonadPlus was the only other option? |
| 19:09:19 | <rubendv> | and than it had to be a Monad too |
| 19:09:22 | <rubendv> | *then |
| 19:09:41 | <byorgey> | you could use Monoid, just give it another argument |
| 19:09:56 | <byorgey> | like instance (Monoid (structure a)) => Monoid (Chat structure a) |
| 19:10:30 | <rubendv> | oh yes of course |
| 19:10:32 | <byorgey> | in fact if you make Chat a newtype instead of data you can just say (deriving Monoid) after it, I think |
| 19:11:16 | <byorgey> | also, the MonadPlus constraint on the data declaration is actually kind of useless |
| 19:12:08 | <seliopou> | byorgey, I believe the newtype deriving requires a language extension |
| 19:12:28 | <byorgey> | yes, it does |
| 19:12:31 | <byorgey> | GeneralizedNewtypeDeriving |
| 19:18:50 | <Baughn> | conal: Actually, there is no bug. This makes me nervous, since it means I don't understand how unsafePerformIO interacts with exceptions. |
| 19:19:23 | <conal> | Baughn: i don't understand either. |
| 19:19:48 | <Baughn> | conal: I'm going to try reading the source. |
| 19:19:58 | <conal> | cool |
| 19:21:01 | <conal> | Baughn: i think Sterling Clover (sclv) and Bertram Felgenhauer (forgot nick) understand. at least better than i do. |
| 19:21:45 | <Baughn> | @seen sclv |
| 19:21:45 | <lambdabot> | I saw sclv leaving #haskell-in-depth, #ghc, #haskell-blah and #haskell 2d 7h 25m 34s ago, and . |
| 19:22:04 | <Baughn> | conal: It might be a case for haskell-cafe, but I'll at least figuring out the source code first |
| 19:24:18 | <Baughn> | Oh yeah. Is it possible to have Emacs read non-Prelude function signatures for eldoc-mode somehow? Perhaps through ghci? |
| 19:27:18 | <Baughn> | "unsafeDupablePerformIO (IO m) = lazy (case m realWorld# of (# _, r #) -> r)" <-- *sigh* |
| 19:33:45 | <defun> | I am confused. Are monads not pure? or is it only the IO monad that is not pure? Furthermore, what is the definition of 'purity' (in the way haskell coders use the term). |
| 19:34:14 | <Cale> | Well, it's subtle. Even the IO monad is pure if you look at it in one way. |
| 19:34:26 | <byorgey> | defun: it is only *running* IO computations which is not pure. |
| 19:34:26 | <rubendv> | I think only the IO a values themselves are magic? |
| 19:34:42 | <Cale> | The IO a values needn't be magic, but interpreting them is. |
| 19:34:48 | <pejo> | defun, "What is a purely functional language": http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.27.7800 |
| 19:35:06 | <byorgey> | defun: often monads are used as a way to package up operations which *appear* to be unpure (e.g. mutable state) in a purely functional way. |
| 19:35:08 | <Cale> | A value of type (IO a) is like a *description* of some stuff to do in order to produce a value of type a |
| 19:35:38 | <Cale> | Carrying out those instructions is the impure bit. |
| 19:35:52 | <Cale> | But just building up a description is pure. |
| 19:35:57 | <rubendv> | So you could say there is a hidden interpreter that executes the IO actions it gets in a lazy list? |
| 19:36:30 | <Cale> | Sort of, or pattern matches on a structure that's been built up (maybe not too list-like) |
| 19:36:41 | <Cale> | and carries out the steps |
| 19:37:07 | <defun> | thanks. |
| 19:37:07 | <Cale> | In a compiled Haskell program, it pattern matches against main, and recursively carries out the instructions described. |
| 19:37:22 | <Cale> | That pattern matching causes Haskell evaluation to happen, which is itself pure. |
| 19:37:50 | <Cale> | So if you were writing a Haskell implementation in Haskell, one possible implementation of IO (if you don't mind the GADT syntax) would be: |
| 19:37:53 | <Cale> | data IO t where |
| 19:37:58 | <Cale> | ReturnIO :: a -> IO a |
| 19:38:08 | <Cale> | BindIO :: IO a -> (a -> IO b) -> IO b |
| 19:38:13 | <Cale> | GetChar :: IO Char |
| 19:38:20 | <Cale> | PutChar :: Char -> IO () |
| 19:38:27 | <Cale> | ... other IO primitives ... |
| 19:38:41 | <Cale> | and then the RTS would have an interpreter for this datatype |
| 19:39:09 | <Cale> | Which, when written in Haskell, looks a bit circular :) |
| 19:39:20 | <rubendv> | :) |
| 19:39:24 | <Cale> | execute (ReturnIO v) = return v |
| 19:39:56 | <Cale> | execute (BindIO x f) = do v <- execute x; execute (f v) |
| 19:40:10 | <Cale> | execute (GetChar) = getChar |
| 19:40:37 | <Cale> | But of course, the first time, it would probably actually be written in something lower level, like C. |
| 19:40:51 | <aias_> | Why does the following not work: http://paste.pocoo.org/show/119808/ (Error message in the code) |
| 19:41:03 | <olsner> | Cale: is that a hypothetical implementation of the RTS in haskell? or would you actually write that as part of the base library? |
| 19:41:19 | <Cale> | olsner: Hypothetical implementation of the RTS. |
| 19:41:37 | <olsner> | so, something like execute :: IO a -> RealIO a? |
| 19:41:43 | <Cale> | yeah |
| 19:42:22 | <Cale> | Just because I didn't feel like writing C-like code for pattern matching ;) |
| 19:42:34 | <olsner> | how would you extend that IO system later? would that only be possible in the base library's definition of the IO type? |
| 19:42:49 | <Cale> | aias_: Because / isn't implemented for Int |
| 19:43:06 | <Cale> | aias_: you'll need to convert x to a fractional type using fromIntegral |
| 19:43:21 | <Cale> | aias_: So you could use f (round (fromIntegral x / 2)) |
| 19:43:29 | <Cale> | But you should also know about div |
| 19:43:42 | <Cale> | olsner: Yeah, FFI is tricky like this. |
| 19:44:11 | <Cale> | olsner: Adding new IO *primitives* needs to be done in that algebraic datatype. |
| 19:44:51 | <olsner> | (unless, of course, the IO type also contains a trapdoor-like thing like UnsafeJumpToAddress :: Word -> IO ()) |
| 19:44:55 | <Cale> | olsner: Though perhaps you could just store enough information to figure out how to do the FFI call. |
| 19:45:02 | <Cale> | yeah |
| 19:45:22 | <aias_> | Cale: Thank you very much. It works perfectly now. |
| 19:45:32 | <olsner> | or FFIFunctionDescriptor a b -> a -> IO b |
| 19:45:44 | <Cale> | aias_: f (x `div` 2) is another option, but it means something slightly different |
| 19:45:53 | <olsner> | which actually also looks kind of sane |
| 19:45:59 | <ninjasamauri> | are you sure that's proper syntax? |
| 19:46:17 | <Cale> | ninjasamauri: what syntax? |
| 19:47:52 | <Cale> | rubendv: Anyway, to get at your actual question more... |
| 19:48:09 | <Cale> | Er, defun rather |
| 19:48:22 | <ninjasamauri> | nevermind i was confused |
| 19:49:12 | <ninjasamauri> | cale you were helping me with a hierarchy db problem |
| 19:49:18 | <ninjasamauri> | decided on a nested set representation |
| 19:49:23 | <aias_> | Cale: Sorry, but I can't see the difference. |
| 19:49:49 | <Cale> | aias_: div is like floor (x/2) and works reliably for large values of x |
| 19:50:09 | <Cale> | defun: The property we usually mean by purity is referential transparency |
| 19:50:50 | <Cale> | defun: What this is, is the property that if two functions f and g always give the same result for the same parameter, then it's safe to replace f with g in the code, without affecting the meaning of the program. |
| 19:51:05 | <Cale> | defun: All mathematical functions have this property |
| 19:51:33 | <Cale> | defun: But, for example, a function which prints something on the screen before producing its result does not. |
| 19:51:39 | <aias_> | Cale: Thank you. I use div now. |
| 19:54:05 | <Cale> | defun: does that help? |
| 19:54:29 | <kuribas> | What does this syntax mean: Module M (Module L, |
| 19:55:05 | <kuribas> | ? |
| 19:55:32 | <Heffalump> | assuming you mean that with module not Module, it means that M re-exports everything it imported from L |
| 19:56:40 | <kuribas> | Ah, yes, module. |
| 19:56:49 | <kuribas> | Heffalump: Ok, I see. |
| 20:00:13 | <gwern> | @quote Zombie.*Jesus |
| 20:00:14 | <lambdabot> | No quotes match. |
| 20:00:20 | <gwern> | @quote zombie |
| 20:00:21 | <lambdabot> | Tac-Tics says: oerjan: I tried, but his zombie lectures were hard to follow |
| 20:00:30 | <gwern> | @quote zombie |
| 20:00:30 | <lambdabot> | Tac-Tics says: oerjan: I tried, but his zombie lectures were hard to follow |
| 20:00:44 | <gwern> | @quote bacon |
| 20:00:44 | <lambdabot> | skorpan says: i love the layout of lyah. makes me feel like having some chunky bacon. |
| 20:00:47 | <gwern> | @quote bacon |
| 20:00:47 | <lambdabot> | skorpan says: i love the layout of lyah. makes me feel like having some chunky bacon. |
| 20:00:56 | <gwern> | drat. what *do* all you people talk about? only one bacon and one zombie quote |
| 20:11:11 | <hackagebot> | convertible 1.0.5 |
| 20:14:55 | <sm> | is there a way to cabal install --reinstall -p (all libs I depend on ?) |
| 20:16:12 | <hackagebot> | HDBC 2.1.1 |
| 20:16:53 | <dcoutts> | sm: not yet no, sorry |
| 20:17:07 | <sm> | ok, thx dcoutts |
| 20:17:15 | <dcoutts> | sm: not automatically, you'll have to track back which things need rebuilding |
| 20:18:38 | <sm> | ACTION depends on five regex libs.. that's just silly |
| 20:18:41 | <ksf> | @remember gwern drat. what *do* all you people talk about? only one bacon and one zombie quote |
| 20:18:41 | <lambdabot> | Good to know. |
| 20:19:10 | <ksf> | lambdabot is a metaquotolar database now. |
| 20:20:52 | <wabash> | curious: do many haskellers dabble in Ocaml, MLton, etc? |
| 20:21:45 | <CosmicRay> | I used ocaml before switching to haskell |
| 20:21:49 | <CosmicRay> | but I made a pretty clean break of it. |
| 20:21:59 | <CosmicRay> | I think there are a number of folks that are familiar with those languages at least |
| 20:22:25 | <wabash> | CosmicRay: How do you feel? Haskell better in some way (your opinion). |
| 20:23:01 | <CosmicRay> | yes, quite so. quite a few things about ocaml annoyed me. the build process was extremely complicated and non-standardized. The I/O library was very weak |
| 20:23:16 | <CosmicRay> | and the separate lists vs. streams was also annoying. |
| 20:23:21 | <CosmicRay> | I like the purity in Haskell |
| 20:23:47 | <ksf> | I know of enough ocaml to prefer haskell, mostly because of purity, and going all the way. I went down the shootout list in search of a proper language to learn, and haskell was (and becomes more and more, all the time) impressive. |
| 20:23:56 | <Cale> | It also seems like a trivial point, but I like Haskell's syntax a lot better. |
| 20:24:01 | <Heffalump> | still a long way to go though |
| 20:24:05 | <CosmicRay> | Cale: I do too. |
| 20:24:13 | <sm> | "Haskell goes all the way" |
| 20:24:40 | <ksf> | well, coming from scheme and c, looking for a replacement for scheme, not c, i wasn't really comfortable with "for". |
| 20:25:19 | <bos31337> | ocaml's only substantial advantage is the module system it inherits from ML. |
| 20:25:50 | <CosmicRay> | that's an advantage? |
| 20:26:39 | <ksf> | modules not messing with semantics, only scoping can be seen as an advantage. |
| 20:26:49 | <wabash> | So... How about math overflow and underflow? Haskell catch it ok? |
| 20:26:53 | <bos31337> | i think so. |