如何在单声道(OS X)中加载.fsx文件,并使用内部类型\函数?

时间:2016-10-07 14:27:15

标签: f# mono f#-interactive

我通过brew install mono在OS X上安装了mono,当我在终端中运行fsharpi时加载了F#v.4.01。

我有一个.fsx文件,用于定义某些类型和功能。我希望在fsifsharpi的别名)中以交互方式使用它们。为此,我启动fsi并运行#load "pc.fsx;;" - 加载并编译文件,我在通用名称空间下看到所有类型定义和函数类型。出于某种原因,REPL无法识别自定义类型(因此我无法使用类型构造函数)和函数,因此我收到错误FS0039:The value or constructor '<insert type or function name>' is not defined。我怎么能克服这个?

编辑: 该文件名为Temp.fsx,内容包含一个名为Temp的模块。

文件内容:

module Temp =

  open System

  /// Type that represents Success/Failure in parsing
  type Result<'a> =
      | Success of 'a
      | Failure of string

  /// Type that wraps a parsing function
  type Parser<'T> = Parser of (string -> Result<'T * string>)

  /// Parse a single character
  let pchar charToMatch =
      // define a nested inner function
      let innerFn str =
          if String.IsNullOrEmpty(str) then
              Failure "No more input"
          else
              let first = str.[0]
          if first = charToMatch then
                  let remaining = str.[1..]
              Success (charToMatch,remaining)
          else
              let msg = sprintf "Expecting '%c'. Got '%c'" charToMatch first
              Failure msg
  // return the "wrapped" inner function
      Parser innerFn

  /// Run a parser with some input
  let run parser input =
      // unwrap parser to get inner function
      let (Parser innerFn) = parser
      // call inner function with input
      innerFn input

fsi的编译输出:

$ fsi

F# Interactive for F# 4.1
Freely distributed under the Apache 2.0 Open Source License

For help type #help;;

> #load "Temp.fsx";;
[Loading /Users/asaf/programming/PCfs/Temp.fsx]

namespace FSI_0002
  module Temp = begin
    type Result<'a> =
      | Success of 'a
      | Failure of string
    type Parser<'T> = | Parser of (string -> Result<'T * string>)
    val pchar : charToMatch:char -> Parser<char>
    val run : parser:Parser<'a> -> input:string -> Result<'a * string>
  end

3 个答案:

答案 0 :(得分:3)

只需在您的AutoOpen [<AutoOpen>] module Temp open System /// Type that represents Success/Failure in parsing type Result<'a> = | Success of 'a | Failure of string /// Type that wraps a parsing function type Parser<'T> = Parser of (string -> Result<'T * string>) /// Parse a single character let pchar charToMatch = // define a nested inner function let innerFn str = if String.IsNullOrEmpty(str) then Failure "No more input" else let first = str.[0] if first = charToMatch then let remaining = str.[1..] Success (charToMatch,remaining) else let msg = sprintf "Expecting '%c'. Got '%c'" charToMatch first Failure msg // return the "wrapped" inner function Parser innerFn /// Run a parser with some input let run parser input = // unwrap parser to get inner function let (Parser innerFn) = parser // call inner function with input innerFn input 模块顶部声明相同的名称,您就可以了:

» fsharpi

F# Interactive for F# 4.1
Freely distributed under the Apache 2.0 Open Source License

For help type #help;;

> #load "Temp.fsx";;
[Loading /Users/kostas/workspace/fsharp/Temp.fsx]

namespace FSI_0002
type Result<'a> =
    | Success of 'a
    | Failure of string
type Parser<'T> = | Parser of (string -> Result<'T * string>)
val pchar : charToMatch:char -> Parser<char>
val run : parser:Parser<'a> -> input:string -> Result<'a * string>

> run (pchar 'f') "foo";;
val it : Result<char * string> = Success ('f', "oo")
> Failure "42";;
val it : Result<'a> = Failure "42"
>

在fsi中加载:

str = "a5bc2cdf3"
str.split(/(\d+)/).each_slice(2).map { |s, c| s * c.to_i }.join # => "aaaaabcbccdfcdfcdf"

答案 1 :(得分:1)

我还没有在.fsx文件中对它进行测试,但我认为它应该可行。您可以将其放入.fs文件中,让我们说File1.fs并将模块声明置于顶部,并执行#load "File1.fs"

然后在FSI中,您可以将xxy称为File1.xxy;;,然后将其创建为File1.B "jds";;

module File1

type A =
    | B of string
    | C of int

let xxy = B "sds"

通常你只需将编辑器中的代码直接发送到FSI并在编辑器中工作,这样你就不会遇到这个问题......

例如

根据你的类型,我得到了:

File1.Failure "blah";;
val it : File1.Result<'a> = Failure "blah"

编辑fsx文件示例:

以下是我的评论中提到的一些变体。文件名为Script11.fsx,模块名称为Temp(指定时)。它只是加载到PowerShell中运行的fsi会话:#load @"Script11.fsx";;

1)没有模块名声明。带文件名的前缀。

open System
type A =
    | B of string
    | C of int

let xxy = B "sds"

//> Script11.xxy;;
//val it : Script11.A = B "sds"
//>

2)Modulename声明。没有缩进。带有modulename的前缀。

module Temp
open System

type A =
    | B of string
    | C of int

let xxy = B "sds"

//> Temp.xxy;;
//val it : Temp.A = B "sds"
//>

3)缩进的modulename(您的版本),带有等号,将模块放在文件名空间中。您可以看到这一点,因为它始于module Temp = begin。带有文件名和模块名的前缀。

module Temp =
    open System

    type A =
        | B of string
        | C of int

    let xxy = B "sds"

//> Script11.Temp.xxy;;
//val it : Script11.Temp.A = B "sds"
//>

4)现在看看Autoopen与否之间的区别:

//[<AutoOpen>]
module Temp =
    open System

    type A =
        | B of string
        | C of int

    let xxy = B "sds"

如果您注释掉Autoopen,则需要在模块名称前加上参考模块的内容。

open Script11;;
Temp.xxy;;
//val it : Temp.A = B "sds"

如果您使用Autopen,则仍需要打开文件名,但您可以直接访问模块内的内容。

> open Script11;;
> xxy;;
//val it : A = B "sds"

简而言之,如果您有顶级声明,通常您不需要Autoopen,如果您不缩进并创建额外的命名空间,您可以直接访问内容。否则你正在创建一个本地模块,显然你必须使用该路径。见Modules

答案 2 :(得分:1)

当您在F#interactive中#load .fsx个文件时,该文件中的所有定义最终都会以文件命名的模块大写。因此,例如,如果您#load "pc.fsx",则所有定义都将以名为Pc的模块结束。

#load "pc.fsx"

let r = Pc.Success "value"