我是Haskell的新手,我试图理解为什么需要编写类型声明.由于Haskell有类型推断,我什么时候需要第一行?GHCI似乎生成正确的输出我用':t'
到目前为止,我发现的唯一一个似乎需要声明的例子如下.
maximum' :: (Ord a) => [a] -> a
maximum' = foldr1 max
Run Code Online (Sandbox Code Playgroud)
但是,如果我添加"-XNoMonomorphismRestriction",则不再需要标志声明.是否存在类型推断不起作用且需要指定类型的特定情况?
由于我可能在类型声明中有错误并且没有直接的好处,我宁愿不写它.我刚刚开始学习Haskell,所以如果我错了请纠正我,因为我想养成良好的习惯.
编辑:事实证明,类型推断是真实世界Haskell书中的一个双刃剑部分,对这个主题进行了很好的讨论.
假设我想创建一个表示可接受的最小/最大边界的记录类型:
type Bounds = { Min: float; Max: float }
Run Code Online (Sandbox Code Playgroud)
有没有办法强制执行Min <Max?编写validateBounds函数很容易,我只是想知道是否有更好的方法来执行此操作.
编辑:我意识到,对于这个具体的例子,我可能会放弃暴露两个属性并重新排序参数,所以让我们说我们试图做
type Person = { Name: string }
Run Code Online (Sandbox Code Playgroud)
和名称需要至少有一个字符.
我只是想知道是否可以使用函数式编程语言(Haskell/F#/ Caml)的模式匹配工具多次匹配相同的值.
试想下面的例子:
plus a a = 2 * a
plus a b = a + b
Run Code Online (Sandbox Code Playgroud)
当使用两个相似的值(将存储在其中a)调用函数时,将调用第一个变体.
一个更有用的应用程序就是这个(简化AST).
simplify (Add a a) = Mult 2 a
Run Code Online (Sandbox Code Playgroud)
但是Haskell拒绝这些代码并警告我有相互矛盾的定义a - 我必须做明确的case/if-checks而不是找出函数是否具有相同的值.是否有任何技巧可以表明我想要匹配的变量会多次出现?
f# haskell functional-programming pattern-matching guard-clause
反引号运算符的固定性是什么?
例如,来自Real World Haskell的代码:
ghci> (1+) `fmap` [1,2,3] ++ [4,5,6]
[2,3,4,4,5,6]
Run Code Online (Sandbox Code Playgroud)
很明显,反引号操作符`fmap`具有更高的固定性++,但GHCi没有给出.
想象一下C#中的以下界面:
interface IFoo {
void Bar();
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能在F#中实现它?我在网上搜索30分钟时发现的所有示例都只显示了返回类型的示例,我认为这些示例在功能样式中更常见,但在这种情况下我无法避免.
这是我到目前为止所拥有的:
type Bar() =
interface IFoo with
member this.Bar() =
void
Run Code Online (Sandbox Code Playgroud)
_FS0010失败:
expression_中出现意外的关键字'void'.
F#是否与C#有相同的问题,你不能直接使用泛型T类型的算术运算符?
你能写一个通用的Sum函数来返回支持算术加法的任何值的总和吗?
我想将一个或多个.fsx文件加载到F#interactive中,并.fsx在范围内的文件中定义所有函数,以便我可以直接使用控制台中的函数.
该#load指令执行.fsx指定的文件,但后来我不再能够在.fsx文件中使用这些函数.有什么解决方法吗?谢谢.
我正在研究一些重的cpu绑定问题.当我使用inline关键字时,我看到了很大的性能提升.我从标准.net库创建一个字典,传入自定义密钥Comparer,请参阅下面的代码和时序结果
https://gist.github.com/4409734
在Eq_cmp上没有内联关键字
> perf_run 10000000 ;;
Real: 00:00:11.039, CPU: 00:00:11.029, GC gen0: 771, gen1: 3, gen2: 1
val it : unit = ()
Run Code Online (Sandbox Code Playgroud)
在Eq_cmp上使用内联关键字
perf_run 10000000 ;;
Real: 00:00:01.319, CPU: 00:00:01.388, GC gen0: 1, gen1: 1, gen2: 1
val it : unit = ()
>
Run Code Online (Sandbox Code Playgroud)
我还注意到Gen 0 GC与内联代码和非内联代码的巨大差异.
有人可以解释为什么会有这么大的差异吗?
如何在F#中编写无操作语句?
具体来说,如何改进以下匹配语句的第二个子句:
match list with
| [] -> printfn "Empty!"
| _ -> ignore 0
Run Code Online (Sandbox Code Playgroud) F#具有称为"类型扩展"的功能,使开发人员能够扩展现有类型.有两种类型的扩展:内在扩展和可选扩展.第一个类似于C#中的部分类型,第二个类似于方法扩展(但更强大).
要使用内部扩展,我们应该将两个声明放入同一个文件中.在这种情况下,编译器会将两个定义合并为一个最终类型(即这是一种类型的两个"部分").
问题是这两种类型对不同的成员和值有不同的访问规则:
// SampleType.fs
// "Main" declaration
type SampleType(a: int) =
let f1 = 42
let func() = 42
[<DefaultValue>]
val mutable f2: int
member private x.f3 = 42
static member private f4 = 42
member private this.someMethod() =
// "Main" declaration has access to all values (a, f1 and func())
// as well as to all members (f2, f3, f4)
printf "a: %d, f1: %d, f2: %d, f3: %d, f4: %d, func(): …Run Code Online (Sandbox Code Playgroud)