从编程生涯的第一天开始,我开始使用面向对象的编程.但是,我有兴趣学习其他范例(我在这里说了很多次这是一件好事,但我没有时间去做).我想我不仅准备好了,而且还有时间,所以我将开始用F#进行函数式编程.
但是,我不确定如何构建更少的设计应用程序.我已经习惯了OO编程中的每类文件和类名词/函数动词.您如何设计和构建功能性应用程序?
这是C#版本:
public static IEnumerable<string> ReadLinesEnumerable(string path) {
using ( var reader = new StreamReader(path) ) {
var line = reader.ReadLine();
while ( line != null ) {
yield return line;
line = reader.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
但直接翻译需要一个可变的变量.
Haskell版本(1.03s):
module Main where
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Control.Monad
import Control.Applicative ((<$>))
import Data.Vector.Unboxed (Vector,(!))
import qualified Data.Vector.Unboxed as V
solve :: Vector Int -> Int
solve ar =
V.foldl' go 0 ar' where
ar' = V.zip ar (V.postscanr' max 0 ar)
go sr (p,m) = sr + m - p
main = do
t <- fmap (read . T.unpack) TIO.getLine -- With Data.Text, the example finishes 15% faster.
T.unlines . map (T.pack …Run Code Online (Sandbox Code Playgroud) 我似乎找不到单声道的编译器/插件.有人存在吗?
在几乎所有的例子中,ML类型语言中的y-combinator都是这样编写的:
let rec y f x = f (y f) x
let factorial = y (fun f -> function 0 -> 1 | n -> n * f(n - 1))
Run Code Online (Sandbox Code Playgroud)
这可以按预期工作,但使用时定义y组合器感觉就像是作弊let rec ....
我想使用标准定义在不使用递归的情况下定义此组合器:
Y = ?f·(?x·f (x x)) (?x·f (x x))
Run Code Online (Sandbox Code Playgroud)
直接翻译如下:
let y = fun f -> (fun x -> f (x x)) (fun x -> f (x x));;
Run Code Online (Sandbox Code Playgroud)
然而,F#抱怨它无法弄清楚类型:
let y = fun f -> (fun x -> f (x x)) (fun x -> f …Run Code Online (Sandbox Code Playgroud) 我试图弄清楚如何定义一个适用于多种类型参数的函数(例如int和int64).据我了解,F#中无法实现函数重载(当然编译器会抱怨).以下面的功能为例.
let sqrt_int = function
| n:int -> int (sqrt (float n))
| n:int64 -> int64 (sqrt (float n))
Run Code Online (Sandbox Code Playgroud)
编译器当然抱怨语法无效(似乎不支持模式匹配中的类型约束),尽管我认为这说明了我想要实现的内容:一个对多个参数类型进行操作并返回相应值的函数类型.我觉得在F#中使用泛型类型/类型推断/模式匹配的某种组合是可能的,但语法已经躲过了我.我也尝试过使用:?操作者(动态型测试)和当在模式匹配块子句,但这仍然会产生各种错误.
由于我对这门语言不熟悉,我很可能会尝试在这里做一些不可能的事情,所以如果有其他解决方案,请告诉我.
所以我开始从tryfsharp.org学习F#,我正在使用VS2013..fs(源),.fsx(脚本)和.fsi(签名)有什么区别?
我一直在学习F#和函数式编程,并试图以功能的方式做事.但是,当我重写一些我已用C#编写的代码时,我会陷入简单的if-then语句(只做一些事情而不返回值).我知道你可以在F#中解决这个问题:
if expr then do ()
Run Code Online (Sandbox Code Playgroud)
但是,我认为这是编码的必要方法?也许我对功能编程学得不够,但它对我来说似乎没什么用.我认为功能方法是组合函数和表达式,而不是简单地一个接一个地执行语句,这是if-then似乎鼓励的.
所以,我错过了什么,如果 - 那么在功能世界中是完美的吗?如果没有,这种陈述的功能等同物是什么?我怎么能拿一个if-then然后把它变成功能呢?
编辑:我可能会问错误的问题(对不起,对于函数式编程来说仍然相当新):让我们采用一个真实世界的例子让我甚至问这个问题:
if not <| System.String.IsNullOrWhiteSpace(data) then do
let byteData = System.Text.Encoding.Unicode.GetBytes(data)
req.ContentLength <- int64 byteData.Length
let postStream : System.IO.Stream = req.GetRequestStream()
postStream.Write(byteData, 0, byteData.Length)
postStream.Flush()
postStream.Dispose()
Run Code Online (Sandbox Code Playgroud)
if-then的主体不返回任何内容,但我不知道如何使其更具功能性(如果可能的话).我不知道最小化命令式代码的正确技巧.考虑到F#的性质,直接运输我的C#相当容易,但是我很难将其转换为功能.每次我在C#中使用if语句,并且我正在尝试将其传输到F#时,我感到气馁,因为我无法想到一种方法来使代码更具功能性.
我正在尝试将Haskell核心库的Arrows转换为F#(我认为这对于更好地理解Arrows和F#是一个很好的练习,我可能能够在我正在开发的项目中使用它们.)但是,直接翻译由于范式的不同,是不可能的.Haskell使用类型类来表达这些东西,但我不确定F#构造最好用F#的习语映射类型类的功能.我有一些想法,但最好把它提到这里,看看哪些被认为是最接近的功能.
对于tl; dr crowd:我如何将类型类(一个Haskell成语)翻译成F#惯用代码?
对于那些接受我长篇解释的人:
来自Haskell标准库的代码是我正在尝试翻译的一个例子:
class Category cat where
id :: cat a a
comp :: cat a b -> cat b c -> cat a c
class Category a => Arrow a where
arr :: (b -> c) -> a b c
first :: a b c -> a (b,d) (c,d)
instance Category (->) where
id f = f
instance Arrow (->) where
arr f = f
first f = f *** id
Run Code Online (Sandbox Code Playgroud)
尝试1:模块,简单类型,让绑定
我的第一个镜头是直接使用模块组织来映射事物,例如:
type Arrow<'a,'b> …Run Code Online (Sandbox Code Playgroud) 我听过很多关于函数式编程语言的知识,我很乐意学习它.我想这主要是为了好玩,但是,我希望它能提高我的编程技巧.
我主要是C#/ .NET背景,所以我的第一选择是学习F#(因为.NET和熟悉Visual Studio).另一方面,我想知道F#是否具有Lisp宏或Haskell高阶函数等功能.
你能比较F#,Haskell和Lisp吗?哪一个将是您选择的语言?
f# ×10
haskell ×3
typeclass ×2
c# ×1
generics ×1
lisp ×1
mono ×1
oop ×1
overloading ×1
performance ×1
ubuntu ×1
ubuntu-9.04 ×1
y-combinator ×1