[Haskell-cafe] Haskell/F#/Ocaml Developer Opportunity in Singapore
Hello Everyone, I am currently recruiting a Functional Programming Developer for one of the bank in Singapore. Anyone interested please contact me at +65-83991283 or please drop a note to me at manimaran_eluma...@kellyit.com.sgwith your contact details. Below are some skills my client is looking for... * Strong in a functional programming language (Haskell, OCaml, F#) * Additional useful languages: C++ / javascript * Maths skills useful. * Good communication skills. * Willingness to interact with traders quants * 1st degree in Computer Science (preferably with some maths courses) * Post grad degree in Computer Science (Msc/Phd) * Publicly available code that can be reviewed. * No finance background required. Regards, Manimaran___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Rigid skolem type variable escaping scope
Matthew Steele asked why foo type-checks and bar doesn't: class FooClass a where ... foo :: (forall a. (FooClass a) = a - Int) - Bool foo fn = ... newtype IntFn a = IntFn (a - Int) bar :: (forall a. (FooClass a) = IntFn a) - Bool bar (IntFn fn) = foo fn This and further questions become much simpler if we get a bit more explicit. Imagine we cannot write type signatures like those of foo and bar (no higher-ranked type signatures). But we can define higher-rank newtypes. Since we can't give foo the higher-rank signature, we must re-write it, introducing the auxiliary newtype FaI. {-# LANGUAGE Rank2Types #-} class FooClass a where m :: a instance FooClass Int where m = 10 newtype FaI = FaI{unFaI :: forall a. (FooClass a) = a - Int} foo :: FaI - Bool foo fn = ((unFaI fn)::(Char-Int)) m 0 We cannot apply fn to a value: we must first remove the wrapper FaI (and instantiate the type using the explicit annotation -- otherwise the type-checker has no information how to select the FooClass instance). Let's try writing bar in this style. The first attempt newtype IntFn a = IntFn (a - Int) newtype FaIntFn = FaIntFn{unFaIntFn:: forall a. FooClass a = IntFn a} bar :: FaIntFn - Bool bar (IntFn fn) = foo fn does not work: Couldn't match expected type `FaIntFn' with actual type `IntFn t0' In the pattern: IntFn fn Indeed, the argument of bar has the type FaIntFn rather than IntFn, so we cannot pattern-match on IntFn. We must first remove the IntFn wrapper. For example: bar :: FaIntFn - Bool bar x = case unFaIntFn x of IntFn fn - foo fn That doesn't work for another reason: Couldn't match expected type `FaI' with actual type `a0 - Int' In the first argument of `foo', namely `fn' In the expression: foo fn foo requires the argument of the type FaI, but fn is of the type a0-Int. To get the desired FaI, we have to apply the wrapper FaI: bar :: FaIntFn - Bool bar x = case unFaIntFn x of IntFn fn - foo (FaI fn) And now we get the desired error message, which should become clear: Couldn't match type `a0' with `a' because type variable `a' would escape its scope This (rigid, skolem) type variable is bound by a type expected by the context: FooClass a = a - Int The following variables have types that mention a0 fn :: a0 - Int (bound at /tmp/h.hs:16:16) In the first argument of `FaI', namely `fn' In the first argument of `foo', namely `(FaI fn)' When we apply FaI to fn, the type-checker must ensure that fn is really polymorphic. That is, free type variable in fn's type do not occur elsewhere type environment: see the generalization rule in the HM type system. When we removed the wrapper unFaIntFn, we instantiated the quantified type variable a with some specific (but not yet determined) type a0. The variable fn receives the type fn:: a0 - Int. To type-check FaI fn, the type checker should apply this rule G |- fn :: FooClass a0 = a0 - Int --- G |- FaI fn :: FaI provided a0 does not occur in G. But it does occur: G has the binding for fn, with the type a0 - Int, with the undesirable occurrence of a0. To solve the problem then, we somehow need to move this problematic binding fn out of G. That binding is introduced by the pattern-match. So, we should move the pattern-match under the application of FaI: bar x = foo (FaI (case unFaIntFn x of IntFn fn - fn)) giving us the solution already pointed out. So my next question is: why does unpacking the newtype via pattern matching suddenly limit it to a single monomorphic type? Because that's what removing wrappers like FaI does. There is no way around it. That monomorphic type can be later generalized again, if the side-condition for the generalization rule permits it. You might have already noticed that `FaI' is like big Lambda of System F, and unFaI is like System F type application. That's exactly what they are: http://okmij.org/ftp/Haskell/types.html#some-impredicativity My explanation is a restatement of the Simon Peyton-Jones explanation, in more concrete, Haskell terms. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] regex-pcre and ghc-7.4.2 is not working with UTF-8
Hello. I think I have an explanation for the problem with regex-pcre, ghc-7.4.2 and UTF Strings. The Text.Regex.PCRE.String module uses the withCString and withCStringLen from the module Foreign.C.String to pass a Haskell string to the C library pcre functions that compile regular expressions, and execute regular expressions to match some text. Recent versions of ghc have withCString and withCStringLen definitions that uses the current system locale to define the marshalling of a Haskell string into a NUL terminated C string using temporary storage. With a UTF-8 locale the length of the C string will be greater than the length of the corresponding Haskell string in the presence with characters outside of the ASCII range. Therefore positions of corresponding characters in both strings do not match. In order to compute matching positions, regex-pcre functions use C strings. But to compute matching strings they use those positions with Haskell strings. That gives the mismatch shown earlier and repeated here with the attached program run on a system with a UTF-8 locale: $ LANG=en_US.UTF-8 ./test1 getForeignEncoding: UTF-8 regex: país:(.*):(.*) text : país:Brasília:Brasil String matchOnce : Just (array (0,2) [(0,(0,22)),(1,(6,9)),(2,(16,6))]) String match : [[pa\237s:Bras\237lia:Brasil,ras\237lia:B,asil]] $ LANG=en_US.ISO-8859-1 ./test1 getForeignEncoding: ISO-8859-1 regex: pa�s:(.*):(.*) text : pa�s:Bras�lia:Brasil String matchOnce : Just (array (0,2) [(0,(0,20)),(1,(5,8)),(2,(14,6))]) String match : [[pa\237s:Bras\237lia:Brasil,Bras\237lia,Brasil]] I see two ways of fixing this bug: 1. make the matching functions compute the text using the C string and the positions calculated by the C function, and convert the text back to a Haskell string. 2. map the positions in the C string (if possible) to the corresponding positions in the Haskell string; this way the current definitions of the matching functions returning text will just work. I hope this would help fixing the issue. Regards, Romildo module Main where import GHC.IO.Encoding (getForeignEncoding) import Data.Bits (Bits((..))) import Text.Regex.PCRE testpcre re text = do putStrLn (regex: ++ re) putStrLn (text : ++ text) putStrLn (String matchOnce : ++ show mo) putStrLn (String match : ++ show m) where c = defaultCompOpt .. compUTF8 e = defaultExecOpt regex = makeRegexOpts c e re :: Regex mo = matchOnce regex text m = match regex text :: [[String]] main = do enc - getForeignEncoding putStrLn (getForeignEncoding: ++ show enc) putStrLn testpcre país:(.*):(.*) país:Brasília:Brasil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] model theory for type classes
{-I am trying to apply model theoretic concepts to Haskell by considering type classes as theories and instances as models.Then the declaration of a sub-class specifies a signature morphism from the superclass to the subclass.In case below the theories (classes) are signature only (no default methods) so a signature morphisms can be considered as a theory morphisms.The only purpose of the code below is to explore the concepts of model expansion[1] and model reduct [2] in HaskellI am not trying to improve or rewrite the code itself for any particular application.Neither am I trying to find OO style inheritance semantics in Haskell type classes.Rather, I am wondering if the last instance of Worker (commented out) demonstrates that there is no model expansion in this case.That is, for theory morphism the theory(Person) = theory(Worker) we do not get (model(Person) sub-model model(Worker)).If there is no model expansion could it be because of the constructor discipline, which only allows variables, and constructors in the LHS argument patterns.[1] http://www.informatik.uni-bremen.de/~cxl/papers/wadt04b.pdf[2] http://en.wikipedia.org/wiki/Reduct-}constant::Intconstant = (1::Int)fun1::Int - Intfun1 (constant::Int) = 8class Person i n | i - n where pid :: i name :: i - n-- There is a signature/theory morphism from Person to Workerclass Person i n = Worker i n s | i - s where salary :: i - s -- model(Person)instance Person Int [Char] where pid = (1::Int) name (1::Int) = (john::[Char])-- We can say that a model(Worker) can use model(Person).instance Worker Int [Char] Int where-- Hypothesis: pid on the RHS shows that a model(Person) is *available* in model(Person) (reduct)? salary i = if i == pid then 100 else 0 -- instance Worker Int [Char] Int where-- Hypothesis: The model of Person cannot be expanded to a model of Worker(no model expansion)-- pid below is not inherited from Person, it is just a local variable-- salary pid = 100 Tá an teachtaireacht seo scanta ó thaobh ábhar agus víreas ag Seirbhís Scanta Ríomhphost de chuid Seirbhísí Faisnéise, ITBÁC agus meastar í a bheith slán. http://www.dit.ie This message has been scanned for content and viruses by the DIT Information Services E-Mail Scanning Service, and is believed to be clean. http://www.dit.ie ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] model theory for type classes
On Thu, Aug 23, 2012 at 01:25:39PM +0100, Patrick Browne wrote: If there is no model expansion could it be because of the constructor discipline, which only allows variables, and constructors in the LHS argument patterns. Indeed, a variable name as a pattern on the LHS of a function definition has nothing to do with any names which might be in scope. It is simply a pattern which matches anything. I am not sure what (if anything) this says about model expansions. constant::Int constant = (1::Int) fun1::Int - Int fun1 (constant::Int) = 8 fun1 returns 8 for all inputs. The fact that fun1's definition uses the name 'constant' which happens to have the same name as something in scope is irrelevant. For example, this is precisely the same as the above: constant :: Int constant = 1 fun1 :: Int - Int fun1 foo = 8 -Brent ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] explicit annotations on kind polymorphism for data types
Not in 7.4.2, correct? -- dude On 08/22/2012 09:58 AM, Brent Yorgey wrote: I believe in the paper it is actually a lowercase Greek chi (χ), which should work too. ;) -Brent On Wed, Aug 22, 2012 at 08:15:48AM +0200, José Pedro Magalhães wrote: Nope, but it should work on 7.6 (also on the release candidate). The 'X' should be lowercase, though, like type variables. Cheers, Pedro On Wed, Aug 22, 2012 at 12:01 AM, dude d...@methodeutic.com wrote: Hello All: I'm working through Giving Haskell a Promotion. Section 2.4 presents an explicitly annotated data type declaration similar to the following: data EqRefl (a::X)(b::X) where Refl :: forall X. forall (a::X). EqRefl a a Has this been implemented in GHC 7.4.2? 7.8.3 in the GHC User Guide leads me to believe it has not. -- dude __**_ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- -- dude ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE basic-prelude-0.3
We are pleased to announce a new release of basic-prelude. http://hackage.haskell.org/package/basic-prelude-0.3.0.0 We apparently weren't entirely clear about the original purpose of basic-prelude, and we got repeated feedback of the form where are the list functions? Somewhat in response to this, we decided to rename the BasicPrelude module to CorePrelude. This module is an *incomplete* prelude, and the goal of this module is to provide enhanced core Prelude functionality *without* making any controversial decisions. CorePrelude serves as the core of Michael's ClassyPrelude, my ModularPrelude, and now the new BasicPrelude module. (If you ever feel the need to create your own Prelude replacement, we encourage you to build it off of CorePrelude. If there is any reason that CorePrelude would not be well-suited to this purpose, then please let us know!) I believe that by using the same Core, it will be easier for these various Prelude replacements to play nice with each other. We created a new module, BasicPrelude (not to be confused with the old BasicPrelude), which *is* a fully-featured Prelude, emphasizing the use of Text and FilePath, while also providing most of the List functions that you know and love, with a few exceptions, as documented. BasicPrelude is among the simplest examples of how we intend CorePrelude to be used. The next time you are working on a hobby project, please try using BasicPrelude instead of regular Prelude, and let us know how it goes! {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} import BasicPrelude -- Dan Burton ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] formal semantics
Dear Haskell Cafe I'm looking for information on past and current attempts to write semantics for Haskell. Features I'm particularly interested in are: - formal - mechanised - maintainable - up to date Of course, if nothing like that exists then partial attempts towards it could still be useful. My ultimate aims include: 1. Make it viable to define Haskell formally (i.e. so mechanised semantics can take over the normative role of the Haskell reports). 2. Write a verified (or verify an existing) Haskell compiler (where verified means semantics preserving). Cheers, Ramana ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] model theory for type classes
On 23/08/12, Brent Yorgey byor...@seas.upenn.edu wrote:fun1 returns 8 for all inputs. The fact that fun1's definition usesthe name 'constant' which happens to have the same name as somethingin scope is irrelevant. For example, this is precisely the same as the above:constant :: Intconstant = 1fun1 :: Int - Intfun1 foo = 8-BrentYes, I am aware the semantics of Haskell is this situation. I also know for every model of a subclass there must exist a model of the super-class. I am just not sure whether there is a model expansion from the super-class model to the subclass model.I am also unsure of the morphism from type variables in the class definition to actual types in instances and to the operations in the instance.In a intuitive way I think that I understand these things, but not in a model theoretic way. Thanks, Pat Tá an teachtaireacht seo scanta ó thaobh ábhar agus víreas ag Seirbhís Scanta Ríomhphost de chuid Seirbhísí Faisnéise, ITBÁC agus meastar í a bheith slán. http://www.dit.ie This message has been scanned for content and viruses by the DIT Information Services E-Mail Scanning Service, and is believed to be clean. http://www.dit.ie ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] regex-pcre and ghc-7.4.2 is not working with UTF-8
On Thu, Aug 23, 2012 at 08:59:52AM -0300, José Romildo Malaquias wrote: Hello. I think I have an explanation for the problem with regex-pcre, ghc-7.4.2 and UTF Strings. The Text.Regex.PCRE.String module uses the withCString and withCStringLen from the module Foreign.C.String to pass a Haskell string to the C library pcre functions that compile regular expressions, and execute regular expressions to match some text. Recent versions of ghc have withCString and withCStringLen definitions that uses the current system locale to define the marshalling of a Haskell string into a NUL terminated C string using temporary storage. With a UTF-8 locale the length of the C string will be greater than the length of the corresponding Haskell string in the presence with characters outside of the ASCII range. Therefore positions of corresponding characters in both strings do not match. In order to compute matching positions, regex-pcre functions use C strings. But to compute matching strings they use those positions with Haskell strings. That gives the mismatch shown earlier and repeated here with the attached program run on a system with a UTF-8 locale: $ LANG=en_US.UTF-8 ./test1 getForeignEncoding: UTF-8 regex: país:(.*):(.*) text : país:Brasília:Brasil String matchOnce : Just (array (0,2) [(0,(0,22)),(1,(6,9)),(2,(16,6))]) String match : [[pa\237s:Bras\237lia:Brasil,ras\237lia:B,asil]] $ LANG=en_US.ISO-8859-1 ./test1 getForeignEncoding: ISO-8859-1 regex: pa�s:(.*):(.*) text : pa�s:Bras�lia:Brasil String matchOnce : Just (array (0,2) [(0,(0,20)),(1,(5,8)),(2,(14,6))]) String match : [[pa\237s:Bras\237lia:Brasil,Bras\237lia,Brasil]] I see two ways of fixing this bug: 1. make the matching functions compute the text using the C string and the positions calculated by the C function, and convert the text back to a Haskell string. 2. map the positions in the C string (if possible) to the corresponding positions in the Haskell string; this way the current definitions of the matching functions returning text will just work. I hope this would help fixing the issue. I have a fix for this bug and it would be nice if others take a look at it and see if it is ok. It is based on the second way presented above. Romildo diff -ur regex-pcre-0.94.4.orig/Text/Regex/PCRE/String.hs regex-pcre-0.94.4/Text/Regex/PCRE/String.hs --- regex-pcre-0.94.4.orig/Text/Regex/PCRE/String.hs2012-05-30 18:44:14.0 -0300 +++ regex-pcre-0.94.4/Text/Regex/PCRE/String.hs 2012-08-23 17:22:14.114641657 -0300 @@ -46,11 +46,16 @@ ) where import Text.Regex.PCRE.Wrap -- all -import Foreign.C.String(withCStringLen,withCString) -import Data.Array(Array,listArray) +import Foreign.C.String(CStringLen,withCStringLen,withCString) +import Foreign.Storable(peekByteOff) +import Data.Word(Word8) +import Data.Array.IO(IOUArray,newArray,readArray,writeArray) +import Data.Array(Array,listArray,bounds,elems) import System.IO.Unsafe(unsafePerformIO) -import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchLength,MatchOffset) +import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchLength,MatchOffset,MatchArray) import Text.Regex.Base.Impl(polymatch,polymatchM) +import GHC.IO.Encoding(getForeignEncoding,textEncodingName) +import Control.Monad(forM) instance RegexContext Regex String String where match = polymatch @@ -72,7 +77,7 @@ matchOnce regex str = unsafePerformIO $ execute regex str = unwrap matchAll regex str = unsafePerformIO $ -withCStringLen str (wrapMatchAll regex) = unwrap +withCStringLen str (wrapMatchAllFixPos regex) = unwrap matchCount regex str = unsafePerformIO $ withCStringLen str (wrapCount regex) = unwrap @@ -91,7 +96,7 @@ -- string, or: -- 'Just' an array of (offset,length) pairs where index 0 is whole match, and the rest are the captured subexpressions. execute regex str = do - maybeStartEnd - withCStringLen str (wrapMatch 0 regex) + maybeStartEnd - withCStringLen str (wrapMatchFixPos 0 regex) case maybeStartEnd of Right Nothing - return (Right Nothing) -- Right (Just []) - fail got [] back! -- should never happen @@ -115,9 +120,94 @@ ,getSub matchedStartStop ,drop stop str ,map getSub subStartStop) - maybeStartEnd - withCStringLen str (wrapMatch 0 regex) + maybeStartEnd - withCStringLen str (wrapMatchFixPos 0 regex) case maybeStartEnd of Right Nothing - return (Right Nothing) -- Right (Just []) - fail got [] back! -- should never happen Right (Just parts) - return . Right . Just . matchedParts $ parts Left err - return (Left err) + + + +-- | wrapMatchFixPos calls wrapMatch and fixes the string offsets +-- in the result so that they are valid in the original Haskell string
[Haskell-cafe] Bringing knowledge from Haskell to Java
Hello everyone. I just posted about a fact that happens to everyone who codes in Java while learning Haskell. You end up trading knowledge from both sides. I'll appreciate if you could read and send me feedbacks: http://me-hunz.blogspot.com.br/2012/08/bringing-knowledge-from-haskell-to-java.html Thanks, Thiago. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Platform Versioning Policy: upper bounds are not our friends
On 8/22/12 9:18 AM, Leon Smith wrote: I think we actually agree more than we disagree; I do think distinguishing hard and soft upper bounds (no matter what they are called) would help, and I'm just trying to justify them to some of the more dismissive attitudes towards the idea Hopefully. Though you suggested conflating the hard/soft distinction and the reactive/proactive distinction, and I can't see how that would even make sense. The former is a matter of ontology (i.e., categorization of what things can/do/should exist), whereas the latter is a matter of policy (i.e., how people can/do/should behave). Clearly there's some relation between the two, but the distinctions are talking about completely different topics. The only thing I think we (might) disagree on is the relative importance of distinguishing hard and soft bounds versus being able to change bounds easily after the fact (and *without* changing the version number associated with the package.) And on that count, given the choice, I pick being able to change bounds after the fact, hands down. Well sure, just updating Cabal to say it has soft upper bounds doesn't mean much unless they're actually overridable somehow ;) I'm still dubious of being able to override hard bounds with a commandline flag. If the hard bound is valid then when you pass the flag to ignore the bound either (a) the code won't compile ---so the flag doesn't help any---, or (b) the code will compile in a way known to be silently wrong/buggy ---so the flag is evil. Circumventing a (valid) hard bound is going to require altering the code, so what benefit is there in avoiding to alter the .cabal file at the same time? The only case I can conceive of it being helpful to circumvent a hard bound is if, in fact, the statement of the hard bound is incorrect. But, if that's the case, it's a bug; and surely correcting that bug should warrant nudging the fourth version number, ne? Also, this situation doesn't strike me as being common enough to warrant the effort of implementation. If it came for free from whatever work it takes to implement soft bounds (which must necessarily be overridable), I wouldn't really care. But if eliminating this burden would help in getting soft bounds implemented, then I see no downside to axing it. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Platform Versioning Policy: upper bounds are not our friends
On 8/22/12 12:35 PM, David Menendez wrote: As I see it, there are four possibilities for a given version of dependency: 1. The version DOES work. The author (or some delegate) has compiled the package against this version and the resulting code is considered good. 2. The version SHOULD work. No one has tested against this version, but the versioning policy promises not to break anything. 3. The version MIGHT NOT work. No one has tested against this version, and the versioning policy allows breaking changes. 4. The version DOES NOT work. This has been tested and the resulting code (if any) is considered not good. Obviously, cases 1 and 4 can only apply to previously released versions. The PVP requires setting upper bounds in order to distinguish cases 2 and 3 for the sake of future compatibility. Leaving off upper bounds except when incompatibility is known essentially combines cases 2 and 3. Right-o. So there are two failure modes: I. A version which DOES work is outside the bounds (that is, in case 3). I think eliminating case 3 is too extreme. I like the idea of temporarily overriding upper bounds with a command-line option. The danger here is that we might actually be in case 4, in which case we don't want to override the bounds, but requiring an explicit override gives users a chance to determine if a particular version is disallowed because it is untested or because it is known to be incompatible. There are two failure modes with overriding stated bounds, however. On the one hand, the code could fail to compile. Okay, we know we're in case 4; all is well. On the other hand the code could successfully compile in ways the package designer knows to be buggy/wrong; we're actually in case 4, but the user does not know this. This is why it's problematic to simply allow overriding constraints. The package developer has some special knowledge that the compiler lacks, but if all constraints are considered equal then the developer has no way to convey that knowledge to the user (i.e., in an automated machine-checkable way). Consequently, the user can end up in a bad place because they thought this second failure mode was actually the success mode. This is why I advocate distinguishing hard constraints from soft constraints. By making this distinction, the developer has a means of conveying their knowledge to users. A soft bound defines an explicit boundary between case 1 and cases 2--4, which can be automatically (per PVP) extended to an implicit boundary between cases 1--2 and cases 3--4; a boundary which, as you say, can only be truly discovered after the code has been published. Extending soft boundaries in this way should be safe; at least it's as safe as possible with the foresight available to us. On the other hand, a hard bound defines an explicit boundary between case 4 and cases 1--3. If these are overridable, things may break silently as discussed above--- but the important thing is, in virtue of distinguishing hard and soft bounds, the user is made aware of this fact. By distinguishing hard and soft bounds, the developer can convey their special knowledge to the user. The user can ignore this information, but at least they'll do so in an informed way. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Rigid skolem type variable escaping scope
On 8/22/12 5:23 PM, Matthew Steele wrote: So my next question is: why does unpacking the newtype via pattern matching suddenly limit it to a single monomorphic type? Some Haskell code: foo :: (forall a. a - Int) - Bool foo fn = ... newtype IntFn a = IntFn (a - Int) bar1 :: (forall a. IntFn a) - Bool bar1 ifn = case ifn of IntFn fn - foo fn bar2 :: (forall a. IntFn a) - Bool bar2 ifn = foo (case ifn of IntFn fn - fn) Some (eta long) System Fc code it gets compiled down to: bar1 = \ (ifn :: forall a. IntFn a) - let A = ??? in case ifn @A of IntFn (fn :: A - Int) - foo (/\B - \(b::B) - fn @B b) bar2 = \ (ifn :: forall a. IntFn a) - foo (/\A - \(a::A) - case ifn @A of IntFn (fn :: A - Int) - fn a) There are two problems with bar1. First, where do we magic up that type A from? We need some type A. We can't just pattern match on ifn--- because it's a function (from types to terms)! Second, if we instantiate ifn at A, then we have that fn is monomorphic at A. But that means fn isn't polymorphic, and so we can't pass it to foo. Now, be careful of something here. The reason this fails is because we're compiling Haskell to System Fc, which is a Church-style lambda calculus (i.e., it explicitly incorporates types into the term language). It is this fact of being Church-style which forces us to instantiate ifn before we can do case analysis on it. If, instead, we were compiling Haskell down to a Curry-style lambda calculus (i.e., pure lambda terms, with types as mere external annotations) then everything would work fine. In the Curry-style world we wouldn't need to instantiate ifn at a specific type before doing case analysis, so we don't have the problem of magicking up a type. And, by parametricity, the function fn can't do anything particular based on the type of its argument, so we don't have the problem of instantiating too early[1]. Of course, (strictly) Curry-style lambda calculi are undecidable after rank-2 polymorphism, and the decidability at rank-2 is pretty wonky. Hence the reason for preferring to compile down to a Church-style lambda calculus. There may be some intermediate style which admits your code and also admits the annotations needed for inference/checking, but I don't know that anyone's explored such a thing. Curry-style calculi tend to be understudied since they go undecidable much more quickly. [1] I think. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] model theory for type classes
On 8/23/12 1:02 PM, Patrick Browne wrote: I am just not sure whether there is a model expansion from the super-class model to the subclass model. If by model expansion from... you mean that there is a canonical/unique/special mapping from every superclass model to some subclass model, then the answer is no. Consider, for instance, applicative functors and monads. We have the (idealized) type classes: class Functor a where... class Functor a = Applicative a where... class Applicative a = Monad a where... However, there are strictly more Applicative instances than there are Monad instances. E.g., lists support an Applicative instance based on zip and an Applicative instance based on the cartesian product; however, only the latter of these can be extended to a Monad. Well, technically, that's only if we assume the appropriate laws are part of the theories defined by the type classes. Without this assumption every type class can be instantiated at every type (for every method f, define f = undefined). -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] When is a composition of catamorphisms a catamorphism?
From page 3 of http://research.microsoft.com/en-us/um/people/emeijer/Papers/meijer94more.pdf : it is not true in general that catamorphisms are closed under composition When is this true? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Conduit: Where to run monad stacks?
I agree that the behavior is a bit confusing (Dan Burton just filed an issue about this[1], I'm guessing this email is related). I put up a wiki page[2] to hopefully explain the issue. Can you review it and let me know if it helps? If so, I'll link to it from the Haddocks. Michael [1] https://github.com/snoyberg/conduit/issues/67 [2] https://github.com/snoyberg/conduit/wiki/Dealing-with-monad-transformers On Wed, Aug 22, 2012 at 11:19 PM, Niklas Hambüchen m...@nh2.me wrote: Today I was surprised that transPipe is called for every chunk of data going through my pipe, rendering the StateT I put in useless, because it was always restarted with the initial value. It would be nice to have some explanation about this, as it makes it easy to write compiling code that has completely unexpected behaviour. I wrote this function (also on http://hpaste.org/73538): conduitWithState :: (MonadIO m) = Conduit Int (StateT Int m) String conduitWithState = do liftIO $ putStrLn $ Counting Int-String converter ready! awaitForever $ \x - do i - lift get lift $ modify (+1) liftIO $ putStrLn $ Converting ++ show x ++ to a string! ++ Processed so far: ++ show i yield (show x) and ran it like this: countingConverterConduit :: (MonadIO m) = Conduit Int m String countingConverterConduit = transPipe (\stateTint - evalStateT stateTint 1) conduitWithState main :: IO () main = do stringList - CL.sourceList [4,1,9,7,3] $= countingConverterConduit $$ CL.consume print stringList However, the output is not what I expected, but only: Processed so far:1 Processed so far:1 ... Dan Burton proposed a fix, making the whole sink-conduit-source construction run on the StateT: main = do stringList - flip evalStateT 1 $ ... So the question is: What is the rationale for this? I was expecting that if I have an IO pipe in my main conduit, I could easily run stuff on top of that in parts of the pipe. Thanks Niklas ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe