robertkennedy 2017-02-22 04:00:05
How can I use DPH? The dph-examples package didn't seem to work on 8.0.1
GuruGuru 2017-02-22 04:18:00
Hello haskellers, I'm trying to learn haskell but i having some trouble with the function signatures
GuruGuru 2017-02-22 04:19:12
I have the following code:
GuruGuru 2017-02-22 04:19:14
listLength :: [a] -> Int listLength [] = 0 listLength a = 1 + listLength (tail a) listSum :: (Num a) => [a] -> a listSum [] = 0 listSum (x:xs) = x + listSum(xs) listMedian :: (Fractional a) => [a] -> a listMedian a = listSum a / fromIntegral (listLength a)
c_wraith 2017-02-22 04:19:45
GuruGuru: I appreciate that you compressed it to a single line, but lpaste is a better way to share code
c_wraith 2017-02-22 04:19:47
@where lpaste
lambdabot 2017-02-22 04:19:48
http://lpaste.net/
robertkennedy 2017-02-22 04:21:06
Your listMedian is the mean, I believe
GuruGuru 2017-02-22 04:21:14
ah sorry, http://lpaste.net/352877
byorgey 2017-02-22 04:21:44
GuruGuru: looks good. What's your question?
GuruGuru 2017-02-22 04:22:01
okay so this works, but what if i want the listMedian function to be able to accept
byorgey 2017-02-22 04:22:08
GuruGuru: (you should write listLength using pattern matching too, like listSum, instead of using tail)
GuruGuru 2017-02-22 04:22:08
lists of Num
kgadek 2017-02-22 04:22:45
GuruGuru: well, then you won't be able to perform division
kgadek 2017-02-22 04:23:03
Fractional class provides that operation
kgadek 2017-02-22 04:23:07
Num doesn't
robertkennedy 2017-02-22 04:23:55
To be clear, you can input Ints just fine - but then when it gets to 3 / 5, what type should that have?
GuruGuru 2017-02-22 04:23:55
But cant a Num be viewed as a fractional
geekosaur 2017-02-22 04:24:00
GuruGuru, types in Haskell do not work like in e.g. Java. a class such as Num (which is *not* a type!) specifies a *maximum* behavior, not a minimum
geekosaur 2017-02-22 04:24:57
if you specify a Num constraint then you are asserting that the capabilities defined in Num are available. nothing else can be used, as the capabilities are not known to be available
kgadek 2017-02-22 04:24:57
GuruGuru: try to think of the type definition as the minimal requirement (as geekosaur mentioned). That function requires division for `a`, therefore you need `Fractional a`
robertkennedy 2017-02-22 04:24:59
Which type should `listMedian [1,2]` have?
GuruGuru 2017-02-22 04:26:10
kgadek, Even if the variable is only used by my sumList function ?
GuruGuru 2017-02-22 04:26:33
which 'returns' a Num
robertkennedy 2017-02-22 04:26:50
But that Num is fed to /
byorgey 2017-02-22 04:26:52
GuruGuru: Num is not a type
geekosaur 2017-02-22 04:26:59
more specifically: ((Num a, ...) => ...) means "make sure that an implementation of Num is passed along, so it can be used to operate on values of type "a"
kgadek 2017-02-22 04:27:04
GuruGuru: look at it in terms of types, not variables
kgadek 2017-02-22 04:27:18
see what happens when you call `listLength your_list_here`
byorgey 2017-02-22 04:27:31
it might sound like I'm being nitpicky, but I think being careful about this will actually help.
kgadek 2017-02-22 04:27:40
`your_list_here` had a type `Fractional => [a]`
kgadek 2017-02-22 04:27:57
Fractional is "stronger" than Num in that Fractional implies Num
kgadek 2017-02-22 04:28:06
therefore you're allowed to call listSum
kgadek 2017-02-22 04:28:11
what you get back?
kgadek 2017-02-22 04:28:18
`Fractional a => a`
kgadek 2017-02-22 04:28:31
that is
max3 2017-02-22 04:28:44
this is bananas to me: why does generateUglifyJS compile but generateCoffeeJS doesn't after adding line 80
kgadek 2017-02-22 04:28:48
`listLength the_list_variable :: Fractional a => a`
max3 2017-02-22 04:28:55
note lines 34 and 80
max3 2017-02-22 04:29:00
http://lpaste.net/352879
kgadek 2017-02-22 04:29:28
GuruGuru: err, my bad
kgadek 2017-02-22 04:31:49
`listLength your_list :: Int`
kgadek 2017-02-22 04:31:57
then you call `fromIntegral` on the result
kgadek 2017-02-22 04:31:57
which gets you `Fractional`
kgadek 2017-02-22 04:31:57
this was the right side of division
kgadek 2017-02-22 04:31:57
the left works quite similarily:
geekosaur 2017-02-22 04:32:01
max3, note that the action on line 34 is bound within: let ioAction = ( do
kgadek 2017-02-22 04:32:02
`listSum` needs `Num a => [a]`, you provide something even finer. So it's fine and this type-checks
geekosaur 2017-02-22 04:32:18
and the ioAction is subsequently passed to webGenerate
kgadek 2017-02-22 04:32:28
and this is the main point here: you get `listSum your_list :: Fractional a => a`
kgadek 2017-02-22 04:32:35
and not `Num a => a`!
geekosaur 2017-02-22 04:32:49
but you are trying to run it directly on line 80
max3 2017-02-22 04:33:14
true
kgadek 2017-02-22 04:33:28
GuruGuru: this is the crucial point. While `listSum` just took the `Num a` constraint, the caller (listMedial) still knows that this `your_list_variable` is finer and more elaborate
kgadek 2017-02-22 04:33:45
therefore, your left side of division is also `Fractional a => a`
max3 2017-02-22 04:33:46
geekosaur, so why can't i?
GuruGuru 2017-02-22 04:33:53
Yes
GuruGuru 2017-02-22 04:34:25
but what if i would like my listmedian function to accept any type of Num list?
byorgey 2017-02-22 04:34:47
GuruGuru: what type should it return?
kgadek 2017-02-22 04:35:14
GuruGuru: look at what Num provides. The `fromInteger` will be your friend :)
GuruGuru 2017-02-22 04:35:27
It can return the Fractorional
geekosaur 2017-02-22 04:35:39
because webRegenerate has access to IO, you do not necessarily. You *may* have access to MonadIO, as that's the easiest way for webRegenerate to have access to IO. In that case, *if* it is appropriate to do so there, you can use liftIO. BUT.
max3 2017-02-22 04:35:52
this is like the perfect storm of being unmaintanable: polymorphic and lazy and strong typed (so i absolutely have to know what type a thing might be even though i have no way of figuring out where it will become what it becomes)
geekosaur 2017-02-22 04:36:20
Remember that these are basically callbacks. It is probably deferring the operation until a time when it makes sense, and performing it directly may be too early / the value you want from the config does not yet exist
byorgey 2017-02-22 04:36:29
GuruGuru: do you mean like listMedian :: (Num a, Fractional b) => [a] -> b ?
kgadek 2017-02-22 04:36:30
( GuruGuru: forget my comment about fromInteger, srsly need more coffee)
GuruGuru 2017-02-22 04:37:39
kgadek, I tried listMedian :: (Num a, Fractorial b) => [a] -> b
byorgey 2017-02-22 04:37:45
GuruGuru: this is impossible: the type says it can return *any* type which is an instance of Fractional, but there is no way to convert between type a and type b, because we don't know what types they are in advance
geekosaur 2017-02-22 04:37:48
max3, do you know the difference between someThing(...) and function(){ someThing(...) } in javascript? that is the difference here
max3 2017-02-22 04:38:07
i don't know what you mean there
byorgey 2017-02-22 04:38:45
GuruGuru: for example I could call it with complex numbers and ask it to return a rational number.
byorgey 2017-02-22 04:39:14
there is no way it can keep that promise.
max3 2017-02-22 04:40:43
how does anyone ever refactor haskell code
geekosaur 2017-02-22 04:40:44
max3 ... you may need to learn about callbacks
max3 2017-02-22 04:41:03
i know about callbacks - i've written plenty of guis
max3 2017-02-22 04:41:06
i don't know js
geekosaur 2017-02-22 04:41:12
yet that did not make sense?
geekosaur 2017-02-22 04:41:15
oh
geekosaur 2017-02-22 04:41:39
the first one performs the action directly. the second is a callback to be run when something is available
c_wraith 2017-02-22 04:42:16
max3: refactoring is the best part of haskell. you make a change, and the compiler tells you everywhere you need to update to support the change.
geekosaur 2017-02-22 04:42:25
that is precisely what happens here: you need to not look up the config now, but tell webRegenerate to do so when it needs the config
geekosaur 2017-02-22 04:42:46
so you need to make it part of the IO action passed to webRegenerate (which is a callback)
geekosaur 2017-02-22 04:43:07
(that is, the IO action is a callback that webRegenerate invokes at the correct time)
max3 2017-02-22 04:43:11
that makes enough sense
max3 2017-02-22 04:44:19
c_wraith, how would i have recognized here for example that the problem was down the line in webRegenerate
max3 2017-02-22 04:44:32
or maybe geekosaur can answer that because he managed to find my repo
jstolarek 2017-02-22 04:44:53
I have a predicate that works in a monad: p :: (Monad m) => ... -> m Bool
jstolarek 2017-02-22 04:45:01
is there a way to use it in a guard?