F#: Unexpected identifier in implementation file
I’ve been playing around with some F# code this evening and one of the bits of code needs to make a HTTP call and return the result.
I wrote this code and then tried to make use of the 'Async.RunSynchronously' function to execute the call.
The code I had looked roughly like this:
namespace Twitter
module RetrieveLinks
open System.Net
open System.IO
open System.Web
open Microsoft.FSharp.Control
let AsyncHttp (url:string) = async {
let request = HttpWebRequest.Create(url)
let! response = request.AsyncGetResponse()
let stream = response.GetResponseStream()
use reader = new StreamReader(stream )
return! reader.AsyncReadToEnd() }
let getData =
let request = "http://some.url"
AsyncHttp <| request
Async.RunSynchronously getData
The problem was I was getting the following error on the last line:
Error 3 Unexpected identifier in implementation file
I’ve seen that error before and it often means that you haven’t imported a reference correctly and hence the compiler doesn’t know what you’re trying to refer to.
In this case I was fairly sure all my references were correct and I was still getting the same error when I used the full namespace to 'Async.RunSynchronously' which seemed to suggest I’d done something else wrong.
After comparing this file with another one which was quite similar but didn’t throw this error I realised that I’d left of the '=' after the module definition. Putting that in solved the problem.
namespace Twitter
module RetrieveLinks =
// and so on
As I understand it if we don’t use the '=' then we’ve created a top level module declaration and if we do use the '=' then we’ve created a local module declaration.
You do not have to indent declarations in a top-level module. You do have to indent all declarations in local modules. In a local module declaration, only the declarations that are indented under that module declaration are part of the module.
Given this understanding another way to solve my problem would be to remove the indentation of the functions inside the module like so:
module RetrieveLinks
open System.Net
open System.IO
open System.Web
open Microsoft.FSharp.Control
// and so on until...
Async.RunSynchronously getData
That compiles as expected.
From reading the MSDN page it would suggest that in my first example I’d created a top level module declaration but indenting the code inside that module somehow meant that the 'Async.RunSynchronously' function wasn’t recognised.
I don’t quite understand why that is so if anyone can enlighten me that would be cool!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.