我通过brew install mono
在OS X上安装了mono,当我在终端中运行fsharpi
时加载了F#v.4.01。
我有一个.fsx
文件,用于定义某些类型和功能。我希望在fsi
(fsharpi
的别名)中以交互方式使用它们。为此,我启动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
答案 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"