<div dir="ltr"><div>Thank you very much</div>
<div> </div>
<div>Nadav Chernin<br><br></div>
<div class="gmail_quote">On Tue, Apr 5, 2011 at 2:56 PM, Daniel Fischer <span dir="ltr"><<a href="mailto:daniel.is.fischer@googlemail.com">daniel.is.fischer@googlemail.com</a>></span> wrote:<br>
<blockquote style="BORDER-LEFT: #ccc 1px solid; MARGIN: 0px 0px 0px 0.8ex; PADDING-LEFT: 1ex" class="gmail_quote">
<div class="im">On Tuesday 05 April 2011 11:57:32, Nadav Chernin wrote:<br>> How can i know when casting of types maked by compiler and when<br>> programmer must to do it?<br><br></div>Generally, there are no implicit type conversions in Haskell, so you always<br>
have to do it explicitly.<br>An exception are numeric literals, an integer literal (in source code or at<br>the ghci/hugs prompt) stands for<br><br>fromInteger (integerValueParsedFromLiteral)<br>-- fromInteger :: Num n => Integer -> n<br>
<br>and a floating-point literal (like 1.234e56) stands for<br><br>fromRational (rationalParsedFromLiteral)<br>-- fromRational :: Fractional a => Rational -> a<br><br>Unless my memory fails, those are the only implicit conversions the<br>
language report specifies. In GHC (I don't know which other compilers, if<br>any, implement it), you can turn on the OverloadedStrings language<br>extension to get overloaded string literals (for instances of the IsString<br>
class), so "this" could be a String , a ByteString or a Text (and some<br>others), provided the relevant modules are in scope.<br><br>Other language extensions providing compiler-generated conversions may<br>exist (now or in future), but I'm not aware of any.<br>
<br>A different, but not unrelated, issue is polymorphism (with type<br>inference).<br>When you use polymorphic expressions - like [], Nothing, (return True),<br>(realToFrac pi) - the compiler uses the context in which the expression<br>
occurs to infer the type at which the expression is used.<br>If that doesn't yield a monomorphic type, under some circumstances the type<br>gets defaulted<br>(<a href="http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4" target="_blank">http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4</a>),<br>
or you get a compile error since the compiler couldn't determine what to<br>do.<br><br>If you don't use any conversion functions,<br><br>mean0 xs = sum xs / length xs,<br><br>the compiler infers<br><br>- xs :: Num n => [n]<br>
(from sum :: Num n => [n] -> n)<br>- sum xs :: Fractional f => f<br>(from (/) :: Fractional f => f -> f -> f)<br>- combining those : xs :: (Num c, Fractional c) => [c]<br>Num is a superclass of Fractional, so the constraint can be simplified,<br>
giving<br>- xs :: Fractional c => [c]<br><br>Then (length xs :: Int), inferred from (length :: [a] -> Int), as the<br>second argument of (/) forces c = Int, giving the type<br><br>mean0 :: Fractional Int => [Int] -> Int<br>
<br>Normally you don't have a Fractional instance for Int in scope, so the<br>compilation would fail with a "No instance ..." error. If you had such an<br>instance in scope, the superfluous because fulfilled constraint would be<br>
removed, giving mean0 :: [Int] -> Int.<br><br>Now, inserting the fromIntegral conversion in the second argument,<br><br>mean1 xs = sum xs / fromIntegral (length xs)<br><br>the first part remains unchanged, resulting in<br>
xs :: Fractional f => [f],<br><br>then (sum xs :: f -- for that same, as yet undetermined Fractional type f)<br>and fromIntegral's result must have the same type f.<br>Since<br><br>fromIntegral :: (Integral i, Num n) => i -> n,<br>
<br>length xs :: Int, Int is an instance of Integral and Num is more general<br>than Fractional, fromIntegral (length xs) can have that type, enabling the<br>compiler to pick the right fromIntegral as soon as it knows f. Overall,<br>
<br>mean1 :: Fractional f => [f] -> f,<br><br>the type f can be determined by passing a list of specific type or using<br>the result at specific type.<br><br>Inserting a conversion for the sum, say realToFrac,<br><br>
mean2 xs = realToFrac (sum xs) / fromIntegral (length xs)<br><br>changes the constraint on the type of xs' elements, now it need no longer<br>be a suitable argument for (/) [Fractional], but for realToFrac [Real].<br>
(realToFrac $ sum xs) has to be the same Fractional type as<br>(fromIntegral $ length xs) but can be any Fractional type, giving<br><br>mean2 :: (Real r, Fractional f) => [r] -> f<br><br>r can only be determined by passing an argument of specific type, f only by<br>
using the result at a specific type.<br>
<div>
<div></div>
<div class="h5"><br>><br>> On Tue, Apr 5, 2011 at 12:14 PM, Daniel Fischer <<br>><br>> <a href="mailto:daniel.is.fischer@googlemail.com">daniel.is.fischer@googlemail.com</a>> wrote:<br>> > On Tuesday 05 April 2011 10:38:37, Nadav Chernin wrote:<br>
> > > Why only "length as" we must to cast? Why "sum as", that have type<br>> > > Integer can be used in (/).<br>> > ><br>> > > :t (/)<br>> > ><br>> > > (/) :: (Fractional a) => a -> a -> a<br>
> ><br>> > No, sum as has the type of as's elements,<br>> ><br>> > sum :: Num a => [a] -> a<br>> ><br>> > So the use of (/) refines the constraint from (Num a) to (Fractional<br>
> > a). if you want it to work on Integers too,<br>> > you'd get<br>> ><br>> > mean :: (Real a, Fractional b) => [a] -> b<br>> > mean xs = realToFrac (sum xs) / (fromIntegral $ length xs)<br>
</div></div></blockquote></div><br></div>