Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Su-Su-Sudoko
Oct 25, 2007

what stands in the way becomes the way

Gloss is pretty nice

Adbot
ADBOT LOVES YOU

VikingofRock
Aug 24, 2008




Testiclops posted:

Gloss is pretty nice

I'm looking over it now and it seems pretty promising. Thanks!

gonadic io
Feb 16, 2011

>>=
Yeah, gloss for sure. It's so handy when doing exactly this kind of simple interactive 2D display that you want. I'm working in F# and I can't find anything like it, I really don't want to have to go all the way to UE4 :(

Mr Shiny Pants
Nov 12, 2012

gonadic io posted:

Yeah, gloss for sure. It's so handy when doing exactly this kind of simple interactive 2D display that you want. I'm working in F# and I can't find anything like it, I really don't want to have to go all the way to UE4 :(

Something like OpenTK? I haven't used it, but it looks like a good library for doing graphics.

Linky: http://www.opentk.com

Smoke_Max
Sep 7, 2011

Hi, Haskell newbie here. I was wondering why main doesn't have a [String] -> IO () type signature like other programming languages, like C/C++ or Java. It would be pretty cool, thanks to pattern matching, to be able to do things like this:

code:
main [arg1, arg2] = ...

main _ = do
	name <- getProgName
	putStrLn ("usage: " ++ name ++ " arg1 arg2")

Smoke_Max fucked around with this message at 15:42 on Jun 3, 2015

gonadic io
Feb 16, 2011

>>=
I know it doesn't directly answer your question, but System.Environment.getArgs will give you that list of strings.

As for why it's not there by default. No idea, historical reasons probably, and it'd be nontrivial to overload to change it now.

edit:
I'd probably do it like one of these two examples, depending on how fancy I was feeling at the time:
code:
mainWithTwoArgs :: String -> String -> IO ()
printUsage :: IO ()

main = do
    args <- getArgs
    case args of
        [a1, a2] -> mainWithTwoArgs a1 a2
        _        -> printUsage

{-# LANGUAGE LambdaCase #-}
advancedMain = getArgs >>= \case
    [a1, a2] -> mainWithTwoArgs a1 a2
    _        -> printUsage

gonadic io fucked around with this message at 17:21 on Jun 3, 2015

Xi over Xi-bar
May 10, 2009
You could do something like
code:
import System.Environment

main = getArgs >>= main' where
  main' [arg1, arg2] = putStrLn $ "Doing important work "++arg1++"ing these "++arg2++"s."
  main' _            = do
    name <- getProgName
    putStrLn $ "usage: " ++ name ++ " arg1 arg2"
I've had good experiences with applicative option parsing in my projects.

sarehu
Apr 20, 2007

(call/cc call/cc)

Smoke_Max posted:

Hi, Haskell newbie here. I was wondering why main doesn't have a [String] -> IO () type signature like other programming languages, like C/C++ or Java. It would be pretty cool, thanks to pattern matching, to be able to do things like this:

That's a relatively arbitrary standardization of C -- main can actually take three arguments on some platforms:

code:
int main(int argc, char **argv, char **envp)
Okay, according to Wikipedia, on OS X it can take a 4th argument.

It's a trendy way to make platform-specific stuff be in a platform-specific library, instead of having it be something that's in the "language". Other languages do it this way too. In Windows the command line is actually a single string, which you'll see if you use WinMain as the entry point, and you have to call GetCommandLineW to get the Unicode version.

sarehu fucked around with this message at 00:49 on Jun 4, 2015

AlexG
Jul 15, 2004
If you can't solve a problem with gaffer tape, it's probably insoluble anyway.

Smoke_Max posted:

Hi, Haskell newbie here. I was wondering why main doesn't have a [String] -> IO () type signature like other programming languages, like C/C++ or Java. It would be pretty cool, thanks to pattern matching, to be able to do things like this:

code:
main [arg1, arg2] = ...

main _ = do
	name <- getProgName
	putStrLn ("usage: " ++ name ++ " arg1 arg2")

This idea is pretty close to what main's signature actually is, if you imagine "IO a" to mean "World -> (a, World)", where World is the type of the rest of the universe. The main function takes a World, emits a value, and also yields a new World, just like other IO actions. Composing IO actions together amounts to threading successive World states through the calls. Unspecified system magic takes care of providing the initial World to the main function at startup. Part of the World is the arguments provided to the program. These are accessible not just in main, but anywhere that we have access to a World. Alternatively, it could make sense to split them off, so main had effective type [String] -> World -> ((), World); and then the arguments could be passed around explicitly wherever they were needed. Or the arguments could be provided as some global constant "args :: [String]", without even an IO type. (For example, this happens with System.Info.os :: String, since we expect the operating system name to be constant over the running life of the program). It so happens that Haskell decided to treat program arguments as part of the World.

Now, we don't actually have access to World values for a few related reasons. One is that the design of IO as an opaque type allows implementers to not have to provide Worlds as a collection of state - IO can be implemented in other ways, much more conveniently. Also, if we could inspect World values, then we could do things which IO is designed to forbid, like saving World copies for later. So all the "get state from the system" style of actions ultimately need to make use of some builtin special functions to do the work, and have an IO type in order to achieve the proper sequencing of actions. The getArgs function is like this; with type "IO [String]" it is as if there is a World coming in (to pull some Strings from), which is provided by some call chain, within the IO monad, up to the initial state of the World provided to main.

Another trick, by the way, is:
code:
import System.Environment

main :: IO ()
main = ...

-- System.Environment.withArgs :: [String] -> IO a -> IO a
-- flip withArgs :: IO a -> [String] -> IO a
-- flip withArgs main :: [String] -> IO ()
mainWithArgs = flip withArgs main

-- now I can call mainWithArgs ["foo", "bar"]
-- and inside main, getArgs will yield ["foo", "bar"]

QuantumNinja
Mar 8, 2013

Trust me.
I pretend to be a ninja.

While your analogy is nice, and the types are more or less on point, this explanation evades the real reason why main doesn't have any arguments: the STG machine needs a starting configuration, and doing so while abstracting over input makes a worse abstract machine. Setting up an STG machine with a main with no arguments makes a lot of sense, because you just build everything into the heap and then you can formally define "invoke main with no arguments" as the start configuration for each machine, uniformly. Otherwise, any theoretical thing you want to do with main in the STG machine requires that you have an existential quantification of the input of main, so that you can say 'there exists some input i such that main {i} runs to completion'. This formalism doesn't take care of additional arguments, either, and that means that i cannot firmly be a value---it has to be some constructor. So now your machine went from "run main and watch it tick" to "pick some constructor that your main will immediately match on to extract I/O information like the initial arguments, and then apply it as main {C x1 x2 ... xn}". Unfortunately, even that doesn't alleviate the headache that your proofs are all going to look like, "There exists C, x_1, ..., x_n, such that main {C x1 x2 ... xn} [does whatever you're trying to prove]".

As a result, and since Haskell was built up from the STG machine, piece by piece, main takes no input and produces no output. Pushing main into the IO monad doesn't break this formalism, because the IO abstractions are just additional functions that live in the global environment of the STG machine as "build-ins" that behave correctly by the time you get down to the STG machine, but rewriting main to explicitly take or return things ruins the underlying abstract model.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Cross-posting from the .NET megathread:

NihilCredo posted:

So if you want to create a WebSharper website, what are your options for good-looking UI controls beside KendoUI?

Athas
Aug 6, 2007

fuck that joker

Smoke_Max posted:

Hi, Haskell newbie here. I was wondering why main doesn't have a [String] -> IO () type signature like other programming languages, like C/C++ or Java. It would be pretty cool, thanks to pattern matching, to be able to do things like this:

code:
main [arg1, arg2] = ...

main _ = do
	name <- getProgName
	putStrLn ("usage: " ++ name ++ " arg1 arg2")

Yet another reason is that there is no guarantee that the contents of argv can be coerced meaningfully to a 'String'. It is just a byte-string, after all. True, 'getArgs' will simply assume that the byte-string encodes text in the native encoding, but at least you have a chance to do something different, which would not be the case if the damage had been done before 'main' was even invoked. Also, the 'String' type is horribly and hilariously inefficient and wasteful, so you may not want to use it.

As for option parsing, I am old-fashioned, so I just use the default GetOpt module. I never saw the point in the more fancy libraries; it's just option parsing.

comedyblissoption
Mar 15, 2006

I talked about Haskell briefly a couple times IRL.

Both times people initially thought I was talking about Pascal.

xtal
Jan 9, 2011

by Fluffdaddy

comedyblissoption posted:

I talked about Haskell briefly a couple times IRL.

Both times people initially thought I was talking about Pascal.

Are you mispronouncing Haskell like I did for a long time? (Or am I still mispronouncing Pascal?)

Pollyanna
Mar 5, 2005

Milk's on them.


Hass-kull.

VikingofRock
Aug 24, 2008




Haskell question: I want to upgrade ghc to 7.10, because a lot of the new stuff looks pretty sweet. What's the best way to do this without breaking everything I've installed with cabal? If that's not possible, what's the best way to fix everything I break?

My Haskell installation is the one provided through https://www.haskell.org/platform/, and it's version 2013.2.0.0 if that matters.

KaneTW
Dec 2, 2011

When you update GHC it creates a new cabal tree for the new version. You'll have to reinstall what you need and recompile existing binaries if they depend on runtime linking like Xmonad. I usually keep the old version around for a while.

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

Use cabal sandboxes for all your projects imo.

Jerry Bindle
May 16, 2003
Scheme question, what is the 'right' way to associate a unique function with an instance of a record type?

I'm decoding opcodes. The process of decoding which instruction the opcode refers to has a regular structure for which I've defined a record type. My question refers to how to then parse the fields. My current solution is to add a lambda expression to the instance that is responsible for determining if a opcode can be decoded by that instruction and parsing out the fields.


code:
(define-record-type instruction 
  . . . 
  (fields 
   . . .
   (immutable opcode->fields)))
This is how I create an instance of a record, with a lambda expression bound to opcode->fields that does the needful unique field decoding
code:
(make-instruction ... 
    (lambda (opcode) 
        (let ([f1-value ..] [f2-value ...]) `((f1 ,f1-value) ...))))
Its used like this

code:
((instruction-opcode->fields (make-instruction ... (lambda ...))) some-opcode)
I have a helper function that searchs through the ISA to find the right instruction so its actual usage isn't so stupid,

code:
(find-instruction->fields some-opcode)
but i still think its kinda stupid, i'm getting that "there is probably a better way to do this that i don't know about" feeling

gonadic io
Feb 16, 2011

>>=
I've got to say, I've really been loving F# lately. Having access to all of C#'s libraries and documentation, access to visual studio (although F# power tools and github integration is required, and resharper recommended). The only things I miss about Haskell tend to be more little-picture in nature: record ADTs with multiple constructors, hackage's ability to search for type signatures, 'where' blocks. My biggest complaint by far is the single-pass compiling which means that you can't really have forward references but you do kind of get used to it after a while.

QuantumNinja
Mar 8, 2013

Trust me.
I pretend to be a ninja.

Barnyard Protein posted:

Scheme question, what is the 'right' way to associate a unique function with an instance of a record type?

I'm decoding opcodes. The process of decoding which instruction the opcode refers to has a regular structure for which I've defined a record type. My question refers to how to then parse the fields. My current solution is to add a lambda expression to the instance that is responsible for determining if a opcode can be decoded by that instruction and parsing out the fields.

...

but i still think its kinda stupid, i'm getting that "there is probably a better way to do this that i don't know about" feeling

The way you've written this up, I'm not 100% certain what you're exactly trying to do. There isn't enough detail here for me to piece out what make-instructio actually does, and what the procedure it takes is expected to do. Also, why does the lambda take an opcode if it's tied to a particular instance of a particular record? Couldn't it just, you know, know its opcode?

I would have expected code that looked like:
code:
((instruction-decode-op record) record)
That is, package up the decoder with the record instance when you create it. Then the constructor is going to be something like
code:
(make-instruction op ... (find-instruction-decode-op op))
Then, obviously, build a wrapper around that so you never had to write it again.

This approach, is, though, pretty OO-like. I would be was lazier about this, and probably just write something like:
code:
(decode-instruction record)

(define decode-instruction
  (lambda (instr)
    (let ((op (instr-opcode instr)))
      (cond
        [(eq? op 'add) ...]
        [(eq? op 'fn) ...]))))
That's how I've always done it when writing compilers and interpreters, abstracting into smaller helpers when possible (like [(if (memq op binops)) (decode-binop-instruction instr)] as a line of the cond). I'd seriously try writing it as a Friedman-style interpreter with records first, and then see what abstraction you really want.

QuantumNinja fucked around with this message at 23:00 on Jun 18, 2015

Jerry Bindle
May 16, 2003
Thanks for the response, I think what you're describing in the first part is what I'm doing, but I'm not sure I understand. I'll have to chew on this for a bit.

Here's a more complete picture of what I'm doing. Decoding happens in two passes, the first pass find the instruction that returns #t from "is-it-one?", the 2nd pass yanks out the instruction fields. I arrived at this approach because I have an urge to keep all information about an instruction and its decoding in one place, but this doesn't even do that. The a-list returned by opcode->fields is a new object disassociated from the instruction. back to the drawing board!

Lisp code:
(let ([add-instruction (make-instruction 
                        'add 
                        'add-x-to-y 
                        #xB40000 ; masks constant 1's in the opcode, all instructions use this type of field
                        #xFF8000 ; masks all non-field bits in the opcode, all instructions use this type of field 
                        (lambda (opcode) ; binds to "opcode->fields". unique for almost every instruction
                          (let ([b-value (bitwise-arithmetic-shift (bitwise-and #x004000 opcode) -14)]
                                [d-value (bitwise-arithmetic-shift (bitwise-and #x002000 opcode) -13)]
                                [f-value (bitwise-and #x001FFF opcode)])
                            `((b ,b-value) (d ,d-value) (f ,f-value)))))]
      [some-opcode #xB44123])

  ; Check to see if some-opcode is an add-instruction
  (display ((instruction-is-it-one? add-instruction) some-opcode)) ; => #t

  ; some-opcode does decode to an add, so get the fields out into an a-list
  (display ((instruction-opcode->fields add-instruction) some-opcode))) ; => {{b 1} {d 0} {f 291}}
Do you have a reference for Friedman-style interpreters?

QuantumNinja
Mar 8, 2013

Trust me.
I pretend to be a ninja.
Yes, I'd do this super-different.

Lisp code:
(define make-add-instruction
  (lambda (opcode)
    (make-instruction 'add
                      'add-x-to-y
                      #xB40000
                      #xFF8000
                      (let ([b-value (bitwise-arithmetic-shift (bitwise-and #x004000 opcode) -14)]
                            [d-value (bitwise-arithmetic-shift (bitwise-and #x002000 opcode) -13)]
                            [f-value (bitwise-and #x001FFF opcode)])
                        `((b . ,b-value) (d . ,d-value) (f . ,f-value))))))

(define add-instr? (lambda (instr) (eq? (instr-type 'add))))

(define add-opcode? (lambda (opcode) ... )) ;; whatever masking op you need here to say yes or no

(define to-instr
  (lambda (opcode)
  (cond
    [(add-opcode? opcode) (make-add-instruction opcode)]
    ...)))

(let* ([some-opcode #xB44123]
       [some-instr (to-instr some-opcode)])
  (display (add-opcode? some-opcode))                  ;; => #t
  (display (add-instr? some-instr))                    ;; => #t
  (display ((instruction-opcode-fields) some-instr)))) ;; => ((b . 1) (d . 0) (f . 291))
The upshot of this is that you can just map to-instr over your list of opcodes and convert them into a list of records that you can then work over. Things like add-instr? and the like will help you write a single cond to dispatch and handle every sort of opcode, and you can use anything written that way in a map, too!

At this point, though, you've pretty much rolled your own ghetto free-for-all facsimile of a record inheritance structure, so use the one in your implementation instead if it's there. In R6RS I'm pretty sure it would look about like this:
Lisp code:
(define-record add-instruction instruction (b d f))
Then you'll write this:
Lisp code:
(define build-new-add-instr
  (lambda (opcode)
    (let ([b-value (bitwise-arithmetic-shift (bitwise-and #x004000 opcode) -14)]
          [d-value (bitwise-arithmetic-shift (bitwise-and #x002000 opcode) -13)]
          [f-value (bitwise-and #x001FFF opcode)])
      (make-add-instruction 'add 'add-x-to-y #xB40000 #xFF8000 b d f))))
The upshot is that then you get add-instruction? for free instead of having to write it, and so dealing with opcodes can just be a large cond that uses add-instruction?, jump-instruction?, ...

The reference is SICP, chapter 4 (it's free online).

(Sorry if there are typos in the above code; I did it without a repl or my usual VIM setup because I'm feeling lazy. I hope it gets the ideas across.)

EDIT: If there are less than 15 opcodes, I actually wouldn't bother writing add-opcode? and the like. I'd just write to-instr using the bit-operation queries on the left of the cond, leave a comment at each test indicating what it was doing, and dump the input in there before doing anything else with it. And if all of the constructors for the instruction records are as simple at the one in build-new-add-instr, I might not even pull those out if I was never, ever going to build a new instruction anywhere else in the program. If you're worried about recovering the opcodes, I'd write instr->opcode that reverses the process.

EDIT2: The procedure you should write and use all over, though, is:

Lisp code:
(define mask-extraction
  (lambda (input field shift)
    (bitwise-arithmetic-shift (bitwise-and field input) shift)))
Then your RHSs are all like:
Lisp code:
(let ([b-value (mask-extraction opcode #x004000 -14)]
      [d-value (mask-extraction opcode #x002000 -13)]
      [f-value (bitwise-and #x001FFF opcode)])
  (make-add-instruction 'add 'add-x-to-y #xB40000 #xFF8000 b d f))

QuantumNinja fucked around with this message at 01:45 on Jun 19, 2015

Dominoes
Sep 20, 2007

Is learning Haskell intended to be an order of magnitude more difficult than other programming languages?

QuantumNinja
Mar 8, 2013

Trust me.
I pretend to be a ninja.
By design, yes!

Mostly, it lacks a good resource for looking up "how do I X" in the language. The wiki book is tolerable, but incomplete. Learn You a Haskell is aimed at people who don't know what a function is, and as far as I can tell Real World Haskell is aimed at C programmers trying to write bar-code scanners in Haskell

Edit: the way everyone I know who has learned Haskell has done it by building something large. It turns into "How do I X" and reading Stack Overflow enough times that at the end you know the language.

Dominoes
Sep 20, 2007

I might try again with another resources. I used LYAH, and it felt more like documentation of every part of the standard library than a tutorial. Something that teaches how to build simple, useful programs using basic features would have been more helpful.

Fullets
Feb 5, 2009
RWH felt to me more like ‘make random poo poo’ but does have the enormous problem that it targets a version of everything from beyond the dawn of time, so nothing works any more.

Other than that I can't think of any obvious resources. At least to me though, once you know the stuff in LYAH doing things in Haskell isn't all that different to everything else; loving round with REST stuff in Haskell using Wreq isn't hugely different to doing it in anything else.

Something that helped a lot of people where I work with Haskell was approaching it via Scala; if you think that'd work for you I guess you could check out Functional Programming in Scala which everyone seemed to like.

comedyblissoption
Mar 15, 2006

Dominoes posted:

Is learning Haskell intended to be an order of magnitude more difficult than other programming languages?
Learning C++ is probably at least just as hard as learning Haskell for programming novices.

Haskell is probably only a magnitude harder than other programming languages when you're already deeply familiar w/ imperative/OOP programming languages. Usually when picking up a new language you just learn new syntax to do the same drat thing you've always done and can re-apply all of your learned experience in a straightforward manner. You've already learned much of what there is to know about the language by having learned prior languages in the same paradigm. When learning a pure functional language with a non-strict evaluation strategy, you can't just re-apply your learned experience in a straightforward manner and have to a learn a bunch of novel concepts.

comedyblissoption fucked around with this message at 06:35 on Jun 19, 2015

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

It basically is designed to be harder to learn than most other programming languages, at least assuming you already know a "normal" programming language. If you know Java and you want to learn C#, you're mostly just going "OK, this is how I do ____ in C#", but with Haskell, you have to learn to approach things from a different direction.

e: the guy above me said it better.

fart simpson fucked around with this message at 07:04 on Jun 19, 2015

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


There's an inherent difficulty in learning Haskell as an imperative programmer, but it's made much worse by the documentation that's out there.

sink
Sep 10, 2005

gerby gerb gerb in my mouf
FP complete articles are getting better.

This works with any language: Start with a simple target like a TODO list web application. Pick a library like Spock or Servant for web stuff, and a friendly database library. Between that documentation, LYAHFGG, and StackOverflow you should be able to limp by. It will be painful at first, but by the end of it you will feel much less crippled and be ready to stroll around the language more confidently.

Edit: Also use stackage and stack https://www.stackage.org/

KaneTW
Dec 2, 2011

https://github.com/bitemyapp/learnhaskell

aerique
Jul 16, 2008
I actually like "Learn You A Haskell". It starts off nice and slow and doesn't immediately go off into la-la land that make most other Haskell tutorials so off-putting.

It was the first thing that I read about Haskell that I could actually follow and made me appreciate the language. This is coming from someone that has been programming for 20+ years in various languages (not that I am any good) of which Common Lisp is my preferred.

Serenade
Nov 5, 2011

"I should really learn to fucking read"
"Learn You a Haskell" mostly worked for me with a few notable gaps.

"Learn You Some Erlang" felt like it took a similar approach but brought me up to speed much more quickly and completely. Possibly because I went into Haskell before Erlang, though.

Jerry Bindle
May 16, 2003

You're awesome, thank you, this is really helpful feedback.

Dominoes
Sep 20, 2007

Hey dudes, Haskell's complaining that none of my variables are in scope. What's up? It does the same when using where in place of let, or 'a' syntax in the type sig.

code:
vap_pres_sat :: Float -> Float
vap_pres_sat temp =
    let T = temp + 273.15  -- Temperature in K
        Tc = 647.096  -- Critical temperature, in K
        Pc = 220640  -- Critical pressure in hPa
        C1 = -7.85951783
        C2 = 1.84408259
        C3 = -11.7866497
        C4 = 22.6807411
        C5 = -15.9618719
        C6 = 1.80122502
        e = 2.71828

        v = 1 - (T / Tc)
    in  e^((Tc / T) * (C1*v + C2*v^1.5 + C3*v^3 + C4*v^3.5 + C5*v^4 + C6*v^7.5)) * Pc

Dominoes fucked around with this message at 07:11 on Jun 21, 2015

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

I don't know exactly what your error message is, but in Haskell, variables have to start with a lowercase letter. If it starts with an uppercase letter, it's a type, so I'm guessing the compiler is complaining the T, Tc, Pc, etc types are not in scope. Try lowercasing them.

gonadic io
Feb 16, 2011

>>=
That is the problem yeah, but not quite the right explanation - types and values are in different namespaces. The two can never be confused as there's never a place in the syntax which could accept either a type name or a value name (at least without wacky extensions).


Dominoes, the rules are that:

Values:
- Start with uppercase = constructor for a datatype (have to be defined with 'data' or 'newtype', and after the '=').
- Start with lowercase = normal value that you define with 'where', 'let', or is a top-level function in a module.

Types:
- Start with uppercase = an actual definite (called concrete) type, defined with 'data', 'newtype' or 'type', before the '='.
- Start with lowercase = a type variable, can turn out to be any concrete type (or you can constrain it using typeclasses and '=>').

e: I ran some similar code and got the error "Not in scope: data constructor 'Butt'". Can you see now why it gives that error? You can't define new data constructors on the fly in 'where' or 'let' blocks (but you CAN pattern match on existing ones there which is why it's not a syntax error).

gonadic io fucked around with this message at 07:49 on Jun 21, 2015

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

Oh yeah sorry, I felt like there was something wrong with my description.

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Thank you for the detailed explanation. It makes sense, and solves the issue I posted. I'm running into a second issue with the code I posted above, after fixing the variable names:

quote:

No instance for (Integral Float) arising from a use of `^'
Possible fix: add an instance declaration for (Integral Float)
In the first argument of `(*)', namely

The nature of the error changes a bit if I change the type signature, but I can't sort it out. It's specifically pointing to my variable e. Note that this is a variable defined within the let, while the type signature should, AFAIK, just deal with input and output variables, which are both floats.

Dominoes fucked around with this message at 08:27 on Jun 21, 2015

  • Locked thread