New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starting F# with Fable: difficulties #1264

Closed
alfonsogarciacaro opened this Issue Nov 29, 2017 · 16 comments

Comments

Projects
None yet
8 participants
@alfonsogarciacaro
Member

alfonsogarciacaro commented Nov 29, 2017

Hi there everybody! If you don't mind me asking, I'd like to know about your experience with F# (note I'm talking about the language here not so much about Fable itself) if you've started learning it and Fable at the same time. If that's your case, could you please post a comment telling briefly:

  • Your programming language background, also if you've already done JS development or you're starting F#/Fable and Frontend all at the same time.
  • The main difficulties you've found while learning F#: syntax, semantics, basic API, documentation, resources, etc.

This will help us make suggestions to the F# design team to help other newcomers in the future. Thanks a lot!

@jordwest

This comment has been minimized.

Show comment
Hide comment
@jordwest

jordwest Nov 29, 2017

I arrived at F# and Fable after some time working with OCaml and Bucklescript, so the landing was pretty smooth. In the .NET world, I had some experience with C#. I've also worked with JavaScript for years.

Overall I've had a really great experience with F# and Fable, everything clicks, the tooling and documentation is excellent. fsharpforfunandprofit.com has been a great resource too.

One thing that still confuses me a bit is the difference between F#'s Async module, the async {} blocks, and C#'s Task, having using async/await in the past. I got a bit lost at first trying to convert a JavaScript callback to an Async<T>, which I guess would be a fairly common task.

Another thing that caught me out (Fable specific) is the [<Import>] attribute. I didn't realize that all attributes need to be attached to some function, so when I wrote this code:

[<Import("default", from="frontend.scss")>]

let init() =
    printfn "Hello world"

init()

The code compiled, but the runtime error was a bit confusing since the attribute was attaching to the init function. After spending quite a while trying to figure out what the problem was, I added a dummy object, which fixed the problem:

[<Import("default", from="frontend.scss")>]
let frontendStyles : obj = jsNative

let init() =
    printfn "Hello world"

init()

Since F# is whitespace sensitive, would it make sense that a function must immediately follow an attribute - ie, on the very next line? Could it be a compiler warning/lint error when the next line is blank?

Lastly, I had a bit of confusion with setting up the development environment - eg I had thought only .net core is needed to compile an app, but then found paket requires mono to install dependencies. Once .NET core and mono was installed though, everything worked perfectly.

Interop was JS is really smooth, and it's so nice to work with a type-safe, pattern matching, powerful language on both the server and in the browser.

jordwest commented Nov 29, 2017

I arrived at F# and Fable after some time working with OCaml and Bucklescript, so the landing was pretty smooth. In the .NET world, I had some experience with C#. I've also worked with JavaScript for years.

Overall I've had a really great experience with F# and Fable, everything clicks, the tooling and documentation is excellent. fsharpforfunandprofit.com has been a great resource too.

One thing that still confuses me a bit is the difference between F#'s Async module, the async {} blocks, and C#'s Task, having using async/await in the past. I got a bit lost at first trying to convert a JavaScript callback to an Async<T>, which I guess would be a fairly common task.

Another thing that caught me out (Fable specific) is the [<Import>] attribute. I didn't realize that all attributes need to be attached to some function, so when I wrote this code:

[<Import("default", from="frontend.scss")>]

let init() =
    printfn "Hello world"

init()

The code compiled, but the runtime error was a bit confusing since the attribute was attaching to the init function. After spending quite a while trying to figure out what the problem was, I added a dummy object, which fixed the problem:

[<Import("default", from="frontend.scss")>]
let frontendStyles : obj = jsNative

let init() =
    printfn "Hello world"

init()

Since F# is whitespace sensitive, would it make sense that a function must immediately follow an attribute - ie, on the very next line? Could it be a compiler warning/lint error when the next line is blank?

Lastly, I had a bit of confusion with setting up the development environment - eg I had thought only .net core is needed to compile an app, but then found paket requires mono to install dependencies. Once .NET core and mono was installed though, everything worked perfectly.

Interop was JS is really smooth, and it's so nice to work with a type-safe, pattern matching, powerful language on both the server and in the browser.

@alfonsogarciacaro

This comment has been minimized.

Show comment
Hide comment
@alfonsogarciacaro

alfonsogarciacaro Nov 29, 2017

Member

Thanks a lot for your comments @jordwest, they're really helpful!

You're right about Async, I do prefer F# Async model now, but I also had some issues in the past when coming from C#. Tomas has a great article about that. And it's true that Async.FromContinuations (to transform a callback into an async) is not very intuitive at first.

I didn't think of the attributes in that sense, as I'm used to have them decorate functions, etc. But I can understand the whitespace is confusing, we can add your suggestion about the warning (it's also possible there're comments in between). BTW, we have now the importSideEffects expression for these cases:

open Fable.Core.JsInterop

importSideEffects "frontend.scss"

let init() =
    printfn "Hello world"

init()

And yes, F# is still transitioning from .NET Framework/Mono to NETCore world. Ionide doesn't need Mono now, and Paket's team is already working to integrate it better with dotnet SDK so hopefully we will have soon a full netcore-only dev environment 😄

Member

alfonsogarciacaro commented Nov 29, 2017

Thanks a lot for your comments @jordwest, they're really helpful!

You're right about Async, I do prefer F# Async model now, but I also had some issues in the past when coming from C#. Tomas has a great article about that. And it's true that Async.FromContinuations (to transform a callback into an async) is not very intuitive at first.

I didn't think of the attributes in that sense, as I'm used to have them decorate functions, etc. But I can understand the whitespace is confusing, we can add your suggestion about the warning (it's also possible there're comments in between). BTW, we have now the importSideEffects expression for these cases:

open Fable.Core.JsInterop

importSideEffects "frontend.scss"

let init() =
    printfn "Hello world"

init()

And yes, F# is still transitioning from .NET Framework/Mono to NETCore world. Ionide doesn't need Mono now, and Paket's team is already working to integrate it better with dotnet SDK so hopefully we will have soon a full netcore-only dev environment 😄

@atlemann

This comment has been minimized.

Show comment
Hide comment
@atlemann

atlemann Dec 1, 2017

Ionide does not need Mono anymore? I have some install scripts to get started with F# on Linux for any newcomers: https://github.com/atlemann/installscripts. Clone it and run install-fsharp-devenv.sh. I need to go learn Fable now...

atlemann commented Dec 1, 2017

Ionide does not need Mono anymore? I have some install scripts to get started with F# on Linux for any newcomers: https://github.com/atlemann/installscripts. Clone it and run install-fsharp-devenv.sh. I need to go learn Fable now...

@alfonsogarciacaro

This comment has been minimized.

Show comment
Hide comment
@alfonsogarciacaro

alfonsogarciacaro Dec 2, 2017

Member

Great @atlemann, thanks for sharing! And yes, Ionide can run on netcore as an opt-in (in theory experimental but I haven't seen any problem... besides Type Providers).

https://twitter.com/k_cieslak/status/932993517445636096

Member

alfonsogarciacaro commented Dec 2, 2017

Great @atlemann, thanks for sharing! And yes, Ionide can run on netcore as an opt-in (in theory experimental but I haven't seen any problem... besides Type Providers).

https://twitter.com/k_cieslak/status/932993517445636096

@whitetigle

This comment has been minimized.

Show comment
Hide comment
@whitetigle

whitetigle Dec 2, 2017

Member

Hi ! I'm sorry I don't have much time to write a long answer today. Still I'll drop just a few words there because it's great you started this thread @alfonsogarciacaro.

So coming from imperative languages mostly OO based (c++, java, action script, haxe and javascript) with a twist of functional via Scala I found my way quite easily through F# via Fable and vice-versa.

I have to say that I have quite a long history of writing bindings for languages. Notably for Haxe for which I wrote many c++, java, and javascript wrappers.

So I have never been really afraid to dive into this area. Although I struggled a bit a at first to understand how to make bidings for fable I was soon able to interact with JS libs. The fact that there was ts2fable to help me was, of course, a very good thing. 👍 And the help you and others from our community offered me has allowed me to vastly speed up things and improve my code. 🥇

Regarding F#. It's an easy to read, easy to use language. Since I wanted to dive at 100% into the functional world and not mess with some hybrid code like I had to do with Scala I have tried so far to avoid OO at all costs.

Regarding Fable, the thing that seem to me the most difficult to understand is the build tool chain. While I now have some experience and make my way, each time we update Fable it seems that we need to update many config files. The fact that the dotnet toolchain has gone through many changes has not helped me as well.

But I feel that it would be great (=I will try to propose a PR) to have up to date versions of the different config files somewhere, in some repo. So that I would just have to make a diff when, let's say, the webpack config changes. 😉

Templates are good. But still the need to understand how to use paket, dotnet, webpack, is important. And that means going through a lot of documentation coming from very different worlds.

I have been through more complicated toolchains but while I think C# users would see how everything works, I guess JS users would have some trouble understand how the whole thing work.

Maybe I'm totally wrong here. But when I want to show F# and Fable around me I cannot sell the quick and dirty factor. That some good news, no? I do not miss the dirty factor. 😆 But the quick factor seems to be really prevalent in the JS community.

With templates I can get started soon. But when things change that's when without documentation or reference config files and without some drawing explaining how everything works it's just easy to lose time for just 2 lines of misconfiguration.

For me that's the only rough edge I see today.

I mean, apart this problem I have been able to do quite anything I had to do without much struggle. And enforcing Elmish has clearly been a real good move 👍

So thank you for everything so far.

Fable is young and is more than promising. I use it already for all my freelance projects. Yes. 100%. So you see that's not bad for a young language/tool 😉

Member

whitetigle commented Dec 2, 2017

Hi ! I'm sorry I don't have much time to write a long answer today. Still I'll drop just a few words there because it's great you started this thread @alfonsogarciacaro.

So coming from imperative languages mostly OO based (c++, java, action script, haxe and javascript) with a twist of functional via Scala I found my way quite easily through F# via Fable and vice-versa.

I have to say that I have quite a long history of writing bindings for languages. Notably for Haxe for which I wrote many c++, java, and javascript wrappers.

So I have never been really afraid to dive into this area. Although I struggled a bit a at first to understand how to make bidings for fable I was soon able to interact with JS libs. The fact that there was ts2fable to help me was, of course, a very good thing. 👍 And the help you and others from our community offered me has allowed me to vastly speed up things and improve my code. 🥇

Regarding F#. It's an easy to read, easy to use language. Since I wanted to dive at 100% into the functional world and not mess with some hybrid code like I had to do with Scala I have tried so far to avoid OO at all costs.

Regarding Fable, the thing that seem to me the most difficult to understand is the build tool chain. While I now have some experience and make my way, each time we update Fable it seems that we need to update many config files. The fact that the dotnet toolchain has gone through many changes has not helped me as well.

But I feel that it would be great (=I will try to propose a PR) to have up to date versions of the different config files somewhere, in some repo. So that I would just have to make a diff when, let's say, the webpack config changes. 😉

Templates are good. But still the need to understand how to use paket, dotnet, webpack, is important. And that means going through a lot of documentation coming from very different worlds.

I have been through more complicated toolchains but while I think C# users would see how everything works, I guess JS users would have some trouble understand how the whole thing work.

Maybe I'm totally wrong here. But when I want to show F# and Fable around me I cannot sell the quick and dirty factor. That some good news, no? I do not miss the dirty factor. 😆 But the quick factor seems to be really prevalent in the JS community.

With templates I can get started soon. But when things change that's when without documentation or reference config files and without some drawing explaining how everything works it's just easy to lose time for just 2 lines of misconfiguration.

For me that's the only rough edge I see today.

I mean, apart this problem I have been able to do quite anything I had to do without much struggle. And enforcing Elmish has clearly been a real good move 👍

So thank you for everything so far.

Fable is young and is more than promising. I use it already for all my freelance projects. Yes. 100%. So you see that's not bad for a young language/tool 😉

@alfonsogarciacaro

This comment has been minimized.

Show comment
Hide comment
@alfonsogarciacaro

alfonsogarciacaro Jan 8, 2018

Member

The fable-scripts repo has been created as the result of the discussion 😄 Hopefully it'll be released in the upcoming days.

Member

alfonsogarciacaro commented Jan 8, 2018

The fable-scripts repo has been created as the result of the discussion 😄 Hopefully it'll be released in the upcoming days.

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 8, 2018

Contributor

Yeah I had some small troubles with imports feeling magical as I was used to require. It turned out instead of doing require, i could use importAll. I also had a bit of confusion when inter op with javascript (not typescript). I didn't have any autocomplete and if I had a typo I would not have known it. Definitely felt like swimming without a life vest. I'm not really sure if what I'm doing there is what I should be doing.

Here's the segment where I imported webtorrent and downloaded a file and added to the document body. It worked but if it hadn't I feel like I would have been worse off than just writing plain js. If there are like good techniques for hooking into js, or building types around JS files that might help.

    let webTorrent = importAll "webtorrent"
    let client = createNew webTorrent ()
    let magnetURI = "magnet:?uri"
    let downloaded t = 
        let f = t?files?find(fun f -> f?name?endsWith(".mp4"))
        f?appendTo("body")
    client?add(magnetURI, downloaded) |> ignore
Contributor

voronoipotato commented Jan 8, 2018

Yeah I had some small troubles with imports feeling magical as I was used to require. It turned out instead of doing require, i could use importAll. I also had a bit of confusion when inter op with javascript (not typescript). I didn't have any autocomplete and if I had a typo I would not have known it. Definitely felt like swimming without a life vest. I'm not really sure if what I'm doing there is what I should be doing.

Here's the segment where I imported webtorrent and downloaded a file and added to the document body. It worked but if it hadn't I feel like I would have been worse off than just writing plain js. If there are like good techniques for hooking into js, or building types around JS files that might help.

    let webTorrent = importAll "webtorrent"
    let client = createNew webTorrent ()
    let magnetURI = "magnet:?uri"
    let downloaded t = 
        let f = t?files?find(fun f -> f?name?endsWith(".mp4"))
        f?appendTo("body")
    client?add(magnetURI, downloaded) |> ignore
@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 8, 2018

Contributor

I do want to be clear I found the documentation a LOT more helpful than a lot of other projects/langs out there, but it would be nice if there were a laid out example of adding types where the TS definitions don't exist. I think for this specific example there exists a TS definition so I'll probably just use TS2Fable, but that won't work if I don't have TS definitions for my own thing I've written and I'd feel silly writing typescript definitions and then generating my F# for it unless that's the agreed upon best path.

Contributor

voronoipotato commented Jan 8, 2018

I do want to be clear I found the documentation a LOT more helpful than a lot of other projects/langs out there, but it would be nice if there were a laid out example of adding types where the TS definitions don't exist. I think for this specific example there exists a TS definition so I'll probably just use TS2Fable, but that won't work if I don't have TS definitions for my own thing I've written and I'd feel silly writing typescript definitions and then generating my F# for it unless that's the agreed upon best path.

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Jan 8, 2018

Contributor

Someone in the chat showed me this. https://github.com/fable-compiler/fable-import

This is exactly what might be helpful :).

Contributor

voronoipotato commented Jan 8, 2018

Someone in the chat showed me this. https://github.com/fable-compiler/fable-import

This is exactly what might be helpful :).

@alfonsogarciacaro

This comment has been minimized.

Show comment
Hide comment
@alfonsogarciacaro

alfonsogarciacaro Jan 8, 2018

Member

@voronoipotato Yes, Fable allows you to do some dynamic programming with F# but you're right is not nice nor idiomatic. To have some kind of type checking when importing JS we would a type checker as powerful as TypeScript which is outside of this project. Personally when I have to write some dynamic code, I just create a util.js file (VS Code helps a lot here), expose a function and then import it into F# like:

let myHelper(name: string, age: int): bool = importMember "./util"

To know more about how to interact with JS from Fable you can check these posts:

http://fable.io/docs/interacting.html
https://medium.com/@zaid.naom/f-interop-with-javascript-in-fable-the-complete-guide-ccc5b896a59f

The fable-import repo contains some bindings maintained by Fable org but there're not many yet.

Member

alfonsogarciacaro commented Jan 8, 2018

@voronoipotato Yes, Fable allows you to do some dynamic programming with F# but you're right is not nice nor idiomatic. To have some kind of type checking when importing JS we would a type checker as powerful as TypeScript which is outside of this project. Personally when I have to write some dynamic code, I just create a util.js file (VS Code helps a lot here), expose a function and then import it into F# like:

let myHelper(name: string, age: int): bool = importMember "./util"

To know more about how to interact with JS from Fable you can check these posts:

http://fable.io/docs/interacting.html
https://medium.com/@zaid.naom/f-interop-with-javascript-in-fable-the-complete-guide-ccc5b896a59f

The fable-import repo contains some bindings maintained by Fable org but there're not many yet.

@rbauduin

This comment has been minimized.

Show comment
Hide comment
@rbauduin

rbauduin Oct 2, 2018

Contributor

Hoping it's fine to give my feedback on this closed issue...

I'm a complete beginner in Fable, .Net and F#, using Linux.
I started by writing a Jupyter notebook, and wanted to convert it to a single page application with
Fable.
Infrastructure put in place by Fable is great. Easy to get started, fable-elmish is a joy to use.
I really enjoyed the experience.
However, I got in trouble when

  • some .Net APIs were not available (for example parsing floats using Culture information).
  • missing some bindings to javascript libraries

If the first was just annoying and manageable, the second one is really getting in the way. My notebook was using fslab, charting with plotly.

However, Fable has binding to Recharts. Converting the code to use Recharts was fine, but then I got some problems to achieve what I wanted. It needed quite some experimentation, and trials and errors to progress: looking at Recharts documentation, searching in the Fable.Recharts binding for properties of the same name, trying to use it and check it works as expected.
I could get the label rotated using this way of working, but I'm still stuck trying to display a time series chart. I've lost so much time on this kind of issue that I'll put this project aside for a moment, which is a pitty as I enjoyed F# and Fable itself.

What I would like to try later on is write all the charting code in javascript or typescript, and just export one function to Fable.
So the binding would have the definition of just one function that I wrote myself, not bindings to the wole library.
Would that be a good approach? If yes, you might want to facilitate it and document it. If not, you might have better suggestions :-)

I'm not sure my experience is representative, but I thought I would share it anyway.

Contributor

rbauduin commented Oct 2, 2018

Hoping it's fine to give my feedback on this closed issue...

I'm a complete beginner in Fable, .Net and F#, using Linux.
I started by writing a Jupyter notebook, and wanted to convert it to a single page application with
Fable.
Infrastructure put in place by Fable is great. Easy to get started, fable-elmish is a joy to use.
I really enjoyed the experience.
However, I got in trouble when

  • some .Net APIs were not available (for example parsing floats using Culture information).
  • missing some bindings to javascript libraries

If the first was just annoying and manageable, the second one is really getting in the way. My notebook was using fslab, charting with plotly.

However, Fable has binding to Recharts. Converting the code to use Recharts was fine, but then I got some problems to achieve what I wanted. It needed quite some experimentation, and trials and errors to progress: looking at Recharts documentation, searching in the Fable.Recharts binding for properties of the same name, trying to use it and check it works as expected.
I could get the label rotated using this way of working, but I'm still stuck trying to display a time series chart. I've lost so much time on this kind of issue that I'll put this project aside for a moment, which is a pitty as I enjoyed F# and Fable itself.

What I would like to try later on is write all the charting code in javascript or typescript, and just export one function to Fable.
So the binding would have the definition of just one function that I wrote myself, not bindings to the wole library.
Would that be a good approach? If yes, you might want to facilitate it and document it. If not, you might have better suggestions :-)

I'm not sure my experience is representative, but I thought I would share it anyway.

@alfonsogarciacaro

This comment has been minimized.

Show comment
Hide comment
@alfonsogarciacaro

alfonsogarciacaro Oct 3, 2018

Member

Thanks a lot for sharing your experience @rbauduin! It's indeed very valuable to know the issues newcomers are facing and improve the development experience.

To create JS bindings from .d.ts declarations, we have ts2fable but it's true it doesn't work well in all situations (especially with React components). For direct interaction with JS you can check this document. In any case, it's difficult to match Typescript capabilities for JS interaction as the language and tooling were basically designed for that. So when you need heavy interaction with JS, it's a good approach to do it in Typescript and then import only the necessary functions from your F# code (you can use the typescript loader or the Babel 7 typescript preset to integrate TS in your Webpack build). There's no specific documentation about it because it shouldn't involve anything else than importing external code but there was recently a post about this issue.

Member

alfonsogarciacaro commented Oct 3, 2018

Thanks a lot for sharing your experience @rbauduin! It's indeed very valuable to know the issues newcomers are facing and improve the development experience.

To create JS bindings from .d.ts declarations, we have ts2fable but it's true it doesn't work well in all situations (especially with React components). For direct interaction with JS you can check this document. In any case, it's difficult to match Typescript capabilities for JS interaction as the language and tooling were basically designed for that. So when you need heavy interaction with JS, it's a good approach to do it in Typescript and then import only the necessary functions from your F# code (you can use the typescript loader or the Babel 7 typescript preset to integrate TS in your Webpack build). There's no specific documentation about it because it shouldn't involve anything else than importing external code but there was recently a post about this issue.

@matthid

This comment has been minimized.

Show comment
Hide comment
@matthid

matthid Oct 3, 2018

@alfonsogarciacaro I can definitely +1 on the experience of @rbauduin as we hit the same thing in our team. Indeed all the information is there and you can find it (or ask on gitter). However, one of the problems for us was that the JS ecosystem overall was new as well, so to get interop working you need to get into F#, how fable transpiles, how webpack works, how javascript works, how typescript works ... and a lot of stuff around that. I think that is just too much to gasp to get an external JS library to work. So I think if we can just get some of these basics away it would be good for new users (either through "special" documentation or other means). Sadly, I have no good suggestion now that we know a bit better how it works together.

matthid commented Oct 3, 2018

@alfonsogarciacaro I can definitely +1 on the experience of @rbauduin as we hit the same thing in our team. Indeed all the information is there and you can find it (or ask on gitter). However, one of the problems for us was that the JS ecosystem overall was new as well, so to get interop working you need to get into F#, how fable transpiles, how webpack works, how javascript works, how typescript works ... and a lot of stuff around that. I think that is just too much to gasp to get an external JS library to work. So I think if we can just get some of these basics away it would be good for new users (either through "special" documentation or other means). Sadly, I have no good suggestion now that we know a bit better how it works together.

@rbauduin

This comment has been minimized.

Show comment
Hide comment
@rbauduin

rbauduin Oct 4, 2018

Contributor

The samples were of great help, and adding a sample using a typescript or javascript library for which there is no Fable binding available would already help a lot. In my specific case, I would then translate that to using plotlyjs. That would answers a lot of questions I have as a (complete) beginner:

  • where do I put my js/ts code using the library?
  • where do I put the bindings to the js/ts functions I want to use from Fable?
  • I suppose I add the js/ts library as a normal dependency. Is that correct?
  • is there anything special to do to use those bindings?
  • is there special to do to have my js/ts code included by webpack?
  • if I use a ts iibrary (so not just using a ts binding to a js library, but really a ts library), does it have to be compiled to to js first? How?

Possibly some or all of those are answered in articles on the web, but having one sample would answer all of them in one place, and it would also show the best practices.

Contributor

rbauduin commented Oct 4, 2018

The samples were of great help, and adding a sample using a typescript or javascript library for which there is no Fable binding available would already help a lot. In my specific case, I would then translate that to using plotlyjs. That would answers a lot of questions I have as a (complete) beginner:

  • where do I put my js/ts code using the library?
  • where do I put the bindings to the js/ts functions I want to use from Fable?
  • I suppose I add the js/ts library as a normal dependency. Is that correct?
  • is there anything special to do to use those bindings?
  • is there special to do to have my js/ts code included by webpack?
  • if I use a ts iibrary (so not just using a ts binding to a js library, but really a ts library), does it have to be compiled to to js first? How?

Possibly some or all of those are answered in articles on the web, but having one sample would answer all of them in one place, and it would also show the best practices.

@0x53A

This comment has been minimized.

Show comment
Hide comment
@0x53A

0x53A Oct 4, 2018

Contributor

Hi @rbauduin, a sample using babylonjs is here: https://github.com/0x53A/FableTsBabylonJsSample

The commit messages contain the commands executed.

  1. Anywhere as a loose file. I normally put them next to the .fs files. You reference them with a relative path.

  2. You mean the F# bindings? I just add the .fs files to my client project. You could also move them to their own project, if you want.

  3. Yes, add them with npm/yarn. Webpack should then find them.

  4. Not really

  5. Yes, you need to add a loader and when using typescript, you need to add .ts / .tsx to the recognized extensions: 0x53A/FableTsBabylonJsSample@196460b#diff-19e2e2ba7026ac670b56c4cb0781b7fb

  6. AFAIK most ts libraries distributed through npm are already compiled - the package contains the .js file (implementation) and the .d.ts file (type declarations).

Contributor

0x53A commented Oct 4, 2018

Hi @rbauduin, a sample using babylonjs is here: https://github.com/0x53A/FableTsBabylonJsSample

The commit messages contain the commands executed.

  1. Anywhere as a loose file. I normally put them next to the .fs files. You reference them with a relative path.

  2. You mean the F# bindings? I just add the .fs files to my client project. You could also move them to their own project, if you want.

  3. Yes, add them with npm/yarn. Webpack should then find them.

  4. Not really

  5. Yes, you need to add a loader and when using typescript, you need to add .ts / .tsx to the recognized extensions: 0x53A/FableTsBabylonJsSample@196460b#diff-19e2e2ba7026ac670b56c4cb0781b7fb

  6. AFAIK most ts libraries distributed through npm are already compiled - the package contains the .js file (implementation) and the .d.ts file (type declarations).

@voronoipotato

This comment has been minimized.

Show comment
Hide comment
@voronoipotato

voronoipotato Oct 4, 2018

Contributor

I've personally found that sometimes it's useful not to import types and to just wrap the weakly typed javascript call with an F# statically typed function, then in your F# function you explicitly declare the types in the parameter definition.

Contributor

voronoipotato commented Oct 4, 2018

I've personally found that sometimes it's useful not to import types and to just wrap the weakly typed javascript call with an F# statically typed function, then in your F# function you explicitly declare the types in the parameter definition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment