Send Beginners mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."
Today's Topics:
1. Re: fromIntegral (Daniel Fischer)
2. Re: fromIntegral (Brandon S Allbery KF8NH)
3. Re: fromIntegral (Russ Abbott)
4. Re: fromIntegral (Brandon S Allbery KF8NH)
5. Counting sheep with the State monad (Amy de Buitl?ir)
6. Re: Counting sheep with the State monad (Brandon S Allbery KF8NH)
----------------------------------------------------------------------
Message: 1
Date: Sun, 3 Oct 2010 00:56:48 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] fromIntegral
To: [email protected]
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
On Saturday 02 October 2010 23:28:59, Thomas wrote:
> So, instantiating Char for Num would require you to provide
> implementations for (+), (*), (-), negate, abs, signum and fromInteger
> for Char.
> While syntactically possible, I don't see any semantically reasonable
> way to do so.
>
For some values of reasonable, defining the operations via the Enum
instance is semantically reasonable.
It's however not the best approach, even if for some odd reason you need
21-bit integers.
> > Is there a way to display a value along with its type during program
> > execution? I know about Show; is there something similar like
> > ShowWithType (or even ShowType) that (if implemented) will generate a
> > string of a value along with its type?
>
> AFAIK in GHCi you can do both, but not simultaneously:
> Prelude> let a = 5::Int
> Prelude> :t a
> a :: Int
> Prelude> a
> 5
>
:set +t
makes ghci display the type of an expression entered at the prompt (except
if it's an IO-action, then it behaves a little different).
> > It makes sense to me to say that [ ] is a function that takes a type
> > as an argument and generates an value. If that's the case, it also
> > makes sense to say that [ ] == [ ] can't be evaluated because there is
> > simply no == for functions.
>
> Prelude> :t []
> [] :: [a]
>
> So [] is a list type, not a function type.
>
Right. [] as a function taking a type as argument is how it's represented
at the Core level in GHC, not how it's understood at the Haskell level or
the assembly level.
> Prelude> [] == []
> True
>
> You can actually compare [] to itself.
At the ghci prompt, since that uses extended default rules and chooses to
compare at the type [()]. In a source file, you'd have to turn on the
extended default rules ({-# LANGUAGE ExtendedDefaultRules #-}) or tell the
compiler which type to use.
>
>
> So your reasoning does not seem to be valid to me.
> At least not on the Haskell source code level (which is what you and
> your students work with). Daniel referred to the Core level when saying
> that [] was a function there.
>
>
> My reasoning would go somewhere along the following line:
> [] has a polymorphic type, specifically it's an empty list of elements
> of any type ([] :: [a], type variable a is not restricted)
>
> So, [] will compare to any empty list, no matter what its elements' type
> actually is.
You need an Eq instance, of course.
>
> Given:
> > let
> > xs = []
> > ys = 1:xs
> > zs = 'a': xs
>
> Then "tail ys == tail zs" will not type check. Neither "tail ys" nor
> "tail zs" are polymorphic:
> ys :: [Integer]
Well, tail ys is polymorphic, its type is
tail ys :: Num a => [a]
the type variable a is defaulted to Integer if there are no further
constraints on a. If you use it for other stuff, it can be used at other
types too.
Prelude> let xs = []; ys = 1:xs; ws = length xs:tail ys; vs = pi:tail ys in
(tail ws, tail vs)
([],[])
it :: (Floating a) => ([Int], [a])
> zs :: [Char]
>
> So the expression "tail ys == tail zs" is invalid - the lhs and rhs must
> have the same type but they do not. Nothing will get compared, no tail
> will be determined - it will just plainly be rejected from the compiler
> (or interpreter).
>
> For comparison: "tail ys == []" is different.
> (tail ys) :: [Integer]
> [] :: [a]
>
> So we set (well, GHC does this for us) type variable a to Integer and
> have: tail ys :: [Integer] == [] :: [Integer]
> which is perfectly valid.
>
Yep.
> > It also makes sense to me to say that == is a collection of more
> > concrete functions from which one is selected depending on the type
> > required by the expression within which == appears.
>
> See above - [] is not a function.
>
> > Since the required type is known at compile time, it would seem that
> > the selection of which == to use could be made at compile time. One
> > shouldn't have to carry along a dictionary. (Perhaps someone said
> > that earlier. But if so, why the long discussion about Dictionaries?)
> > This seems like a standard definition of an overloaded function. So
> > why is there an objection to simply saying that == is overloaded and
> > letting it go at that?
>
> (==) :: (Eq a) => a -> a -> Bool
>
> So, yes, (==) feels a little like an overloaded function.
And such functions are often called overloaded.
> It is a function that accepts any Eq-comparable type.
> However, overloading IIRC does not behave identically.
Overloading in Java, C# etc. behaves differently. Overloading is still a
good term to describe (==) etc. in my opinion. One has to be aware that the
word denotes different though related concepts for different languages, of
course.
> For example function arity is not required to be the same when
> overloading methods - and restrictions on types are very different, too.
>
> HTH,
> Thomas
------------------------------
Message: 2
Date: Sat, 02 Oct 2010 18:58:02 -0400
From: Brandon S Allbery KF8NH <[email protected]>
Subject: Re: [Haskell-beginners] fromIntegral
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 10/2/10 17:28 , Thomas wrote:
>> Is there a way to display a value along with its type during program
>> execution? I know about Show; is there something similar like ShowWithType
>> (or even ShowType) that (if implemented) will generate a string of a value
>> along with its type?
>
> AFAIK in GHCi you can do both, but not simultaneously:
> Prelude> let a = 5::Int
> Prelude> :t a
> a :: Int
> Prelude> a
> 5
Data.Typeable.typeOf works for monomorphic types. I think there's some Oleg
deep magic for (a subset of?) polymorphic types.
> Prelude> [] == []
> True
>
> You can actually compare [] to itself.
This only works in ghci, because of extended defaulting; both []s are given
the type [()]. In GHC proper, unless you explicitly enable the extended
defaulting rules, defaulting only works for numeric types; [] won't compare
to [] because neither can be typed, but [0] compares to [0] despite 0 being
polymorphic (depending on context it can be any instance of typeclass Num)
because defaulting gives it the type Integer.
>> It also makes sense to me to say that == is a collection of more concrete
>> functions from which one is selected depending on the type required by the
>> expression within which == appears.
>
> See above - [] is not a function.
[] isn't relevant here.
>> Since the required type is known at compile time, it would seem that the
>> selection of which == to use could be made at compile time. One shouldn't
Not always; Haskell is "open", by default all functions are exported from
modules and therefore use in another module must be considered by the
compiler unless you told it not to export it.
If you turn on optimization, then the compiler *may* decide to "specialize"
particular uses of (==) to avoid the dictionary --- provided it can prove
that it knows all the possible types that the particular use can take. (You
can influence this by use of the {-# SPECIALIZE #-} pragma; see the ghc manual.)
>> standard definition of an overloaded function. So why is there an objection
>> to simply saying that == is overloaded and letting it go at that?
Precision. "Overloading" as it's normally used with respect to programming
languages doesn't constrain what the overloads do. Imagine, if you will,
what the typeclass dictionary for C++'s "<<" (which in Haskell is
(Data.Bits.shiftL :: Bits b => b -> Int -> b)) would look like, and how you
would define, say, Data.Bits.bit for the ostream variant.
Aside: Haskell doesn't try to prove that a given instance of a typeclass
makes sense beyond making sure the types match, but users of the typeclass
can and do assume they make sense; also, type inference can lead the
compiler to do unexpected things when oddball instances such as Num Char are
defined, in expressions where one would not expect that instance to be used.
This is one reason why many of us use type inference only sparingly;
specifying the types you expect in as many places as possible both
sanity-checks your thinking and helps force type errors to be detected where
they actually occur instead of where type inference causes the compiler to
realize something doesn't make sense, which may be in a completely different
function elsewhere. This may be most common with numeric types, where
forgetfully using (/) on an Int or Integer causes the compiler to say it
can't find a a type that is both Integral and Fractional somewhere else
where the result of said (/) is ultimately passed to something requiring an
Integral instance.
> For example function arity is not required to be the same when overloading
> methods - and restrictions on types are very different, too.
(==) is a poor example here, as most languages won't let you alter the arity
of operators.
- --
brandon s. allbery [linux,solaris,freebsd,perl] [email protected]
system administrator [openafs,heimdal,too many hats] [email protected]
electrical and computer engineering, carnegie mellon university KF8NH
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkynuPoACgkQIn7hlCsL25XsQgCgmCrP6TF9a2+jUE07KxhM4Cj4
n8UAoJWsBCvlogvZsU9/5eWXqtszfmPM
=3ta5
-----END PGP SIGNATURE-----
------------------------------
Message: 3
Date: Sat, 2 Oct 2010 16:59:09 -0700
From: Russ Abbott <[email protected]>
Subject: Re: [Haskell-beginners] fromIntegral
To: Daniel Fischer <[email protected]>
Cc: [email protected]
Message-ID:
<[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
> Perhaps it's best to say that for the time being, they should regard
> polymorphic expressions like [] as either one symbol denoting different
> values of different types or one value having many types, whichever they
> feel more comfortable with.
>
I would like to be able to say that [ ] is one symbol denoting different
values of different types and that the compiler picks which value it denotes
given the context. But the example program disallows that--which is how I
came up with the example in the first place.
let
xs = []
ys = 1:xs
zs = 'a': xs
in ...
xs is not bound to a value with a concrete type (like [Int] or [Char]) at
compile time. Even after compilation xs :: [a].
To say that [ ] is a value having many different types seems to be saying
more or less the same thing, namely that compilation doesn't pick a
particular concrete type.
So what are the other options? I still like the idea of saying that [ ] is a
function that takes a type as an argument and generates a value. (I believe
this was your explanation at one point.) I realize that it isn't a function
at the Haskell level. But it makes intuitive sense to say that the compiler
generates such a function, which is what is bound to xs. It is that function
that gets executed when the program is run. I know that for optimization
purposes it may be compiled down past that interpretation and I also know
that this function isn't a Haskell function. But if one were giving an
operational semantics for what's going on (which I guess is what the Core
effectively is) that seems to be the most transparent explanation.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://www.haskell.org/pipermail/beginners/attachments/20101002/de5ae329/attachment-0001.html
------------------------------
Message: 4
Date: Sat, 02 Oct 2010 20:41:11 -0400
From: Brandon S Allbery KF8NH <[email protected]>
Subject: Re: [Haskell-beginners] fromIntegral
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 10/2/10 19:59 , Russ Abbott wrote:
> So what are the other options? I still like the idea of saying that [ ] is a
> function that takes a type as an argument and generates a value. (I believe
The best way to think abut this isn't really in terms of functions. The
whole point of functional programming is referential transparency: in "let
xs = [] ...", xs can be seen as a sort of "macro" which stands for its
expansion. So you can use xs anywhere you would use [] and it will always
behave as if you said [], including the polymorphism. Anywhere you use a
binding, you are always able to substitute the bound expression.
(This is why we need "magic" for IO. Conceptually, an IO "action" is a
partial function which won't run until passed the baton; this same partial
function can be substituted anywhere, but each substitution will be lazily
evaluated when the baton reaches it (if in fact it ever does). The IO monad
hides the baton-passing and makes sure it's done in legitimate ways. So in
fact IO "actions" are entirely referentially transparent.)
- --
brandon s. allbery [linux,solaris,freebsd,perl] [email protected]
system administrator [openafs,heimdal,too many hats] [email protected]
electrical and computer engineering, carnegie mellon university KF8NH
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkyn0ScACgkQIn7hlCsL25WtkACgy5bTsmQJATu9zSL29v3uX5Pg
3GoAn2QfkWhfNU3cbl0/ZKLjnS9VzZFm
=I+TE
-----END PGP SIGNATURE-----
------------------------------
Message: 5
Date: Sun, 3 Oct 2010 05:20:53 +0100
From: Amy de Buitl?ir <[email protected]>
Subject: [Haskell-beginners] Counting sheep with the State monad
To: beginners <[email protected]>
Message-ID:
<[email protected]>
Content-Type: text/plain; charset=ISO-8859-1
I've written a very simple piece of code in order to help me
understand Monads better:
----------
import "mtl" Control.Monad.State
countAnotherSheep :: Int -> (String, Int)
countAnotherSheep n = (show n ++ " sheep", n+1)
sheepCounter = State { runState = countAnotherSheep }
----------
So far so good. Now I can do things like:
ghci> evalState sheepCounter 1
"1 sheep"
ghci> evalState sheepCounter 2
"2 sheep"
ghci> execState sheepCounter 1
2
ghci> execState sheepCounter 2
3
ghci> evalState (sequence $ replicate 5 sheepCounter) 1
["1 sheep","2 sheep","3 sheep","4 sheep","5 sheep"]
But what I really want to do is create a main function in which I:
1. Count some sheep.
2. Do something else.
3. Count some more sheep, picking up where I left off.
I could thread the state like this:
increment (_, n) = countAnotherSheep n
main = do
let c = countAnotherSheep 1
putStrLn $ fst c
let c2 = increment c
putStrLn $ fst c2
putStrLn "Now I'll do some other stuff"
let c3 = increment c2
putStrLn $ fst c3
... but shouldn't the State monad make threading the state
unnecessary? It seems like there should be a way to do this, but I
can't figure it out. Thank you in advance for any suggestions.
------------------------------
Message: 6
Date: Sun, 03 Oct 2010 01:22:05 -0400
From: Brandon S Allbery KF8NH <[email protected]>
Subject: Re: [Haskell-beginners] Counting sheep with the State monad
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 10/3/10 00:20 , Amy de Buitléir wrote:
> I've written a very simple piece of code in order to help me
> understand Monads better:
>
> ----------
> import "mtl" Control.Monad.State
>
> countAnotherSheep :: Int -> (String, Int)
> countAnotherSheep n = (show n ++ " sheep", n+1)
>
> sheepCounter = State { runState = countAnotherSheep }
> ----------
>
> So far so good. Now I can do things like:
>
> ghci> evalState sheepCounter 1
> "1 sheep"
> ghci> evalState sheepCounter 2
> "2 sheep"
>
> ghci> execState sheepCounter 1
> 2
> ghci> execState sheepCounter 2
> 3
>
> ghci> evalState (sequence $ replicate 5 sheepCounter) 1
> ["1 sheep","2 sheep","3 sheep","4 sheep","5 sheep"]
>
> But what I really want to do is create a main function in which I:
>
> 1. Count some sheep.
> 2. Do something else.
> 3. Count some more sheep, picking up where I left off.
>
> I could thread the state like this:
>
> increment (_, n) = countAnotherSheep n
>
> main = do
> let c = countAnotherSheep 1
> putStrLn $ fst c
> let c2 = increment c
> putStrLn $ fst c2
> putStrLn "Now I'll do some other stuff"
> let c3 = increment c2
> putStrLn $ fst c3
>
> ... but shouldn't the State monad make threading the state
> unnecessary? It seems like there should be a way to do this, but I
> can't figure it out. Thank you in advance for any suggestions.
You're overthinking it. The State monad is defined in terms of those
operations precisely so it can hide/abstract them. The way you actually use
it is:
> countSheepAndStuff :: State Int ()
> countSheepAndStuff = do
> countAnotherSheep 1
> doSomethingElsePossiblyCountingMoreSheep
> countAnotherSheep 1
> -- countAnotherSheep 1 >> doSomethingElse... >> countAnotherSheep 1
>
> countAnotherSheep :: Int -> State Int ()
> countAnotherSheep howmany = modify (+ howmany)
> -- or: countAnotherSheep = modify . (+)
>
> doSomethingElsePossiblyCountingMoreSheep :: State Int ()
> doSomethingElsePossiblyCountingMoreSheep = undefined -- you tell me :)
>
> main = do
> -- this throws out the () and keeps the final state/sheep count
> let sheep = execState countSheepAndStuff 0
> putStrLn $ show sheep ++ " sheep total"
You never construct State values manually; while runState looks like a
record accessor (and in fact is), it's actually used to send something
through a State monad without ever actually creating an explicit State. The
trick here is that the accessor runState's type is a function (s -> (a,s));
if you pass a function of the appropriate type, you are implicitly creating
a State record, and if you then use the methods and the monad machinery (do
or (>>=)/(>>)) you never need to create or touch an actual State value anywhere.
> runState (modify (+1) >> modify (+3)) 0
The type of the parameter to runState here is State Integer () (which is
really Integer -> ((),Integer)), and then we pass an Integer to that
function to kick things off. The Integers come from defaulting based on the
0, 1, and 3, and the () from the definition of the modify function (modify
:: s -> State s (), with s set to Integer by aforementioned defaulting).
The result is the tuple ((),4). Since you don't need or care about the (),
you probably would use execState instead of runState in practice.
For the countAnotherSheep you used in your example, constructing lists of
Strings, you may want to consider another monad: Writer. When you get to
that point, you can explore how to do it with a monad transformer WriterT
[String] (State Int) () or the reverse transformer StateT Int (Writer
[String]) (), and the situations under which you would want to prefer one or
the other.
- --
brandon s. allbery [linux,solaris,freebsd,perl] [email protected]
system administrator [openafs,heimdal,too many hats] [email protected]
electrical and computer engineering, carnegie mellon university KF8NH
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkyoEv0ACgkQIn7hlCsL25XorQCghdnWCqRpToRLMB6rnCtZX/nX
lAoAnRlVQihEBsH8NRLWzaJUxUf3vZz4
=pqwT
-----END PGP SIGNATURE-----
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 28, Issue 10
*****************************************