我正在探索Haskell中的选项,这些选项使我可以将业务逻辑与基础系统的技术实现区分开。例如,在Web服务器的上下文中,将Web服务器如何处理其接收的信息与从数据库中读取和写入数据库的方式分开。为此,有很多选择,但有两个特别引起我的注意:“免费Monad”和将能力记录作为参数传递。我很难看到一个相对于另一个的利弊。
一个代码片段来说明我在说什么:
module Lib where
import qualified Control.Monad.Free as FreeMonad
data MyGadt x
= Read (String -> x)
| Write String
x
instance Functor MyGadt where
fmap f (Read g) = Read (f . g)
fmap f (Write str x) = Write str (f x)
programWithFreeMonad :: FreeMonad.Free MyGadt ()
programWithFreeMonad = do
msg <- FreeMonad.liftF $ Read id
FreeMonad.liftF $ Write msg ()
ioInterpreter :: FreeMonad.Free MyGadt x -> IO x
ioInterpreter (FreeMonad.Pure x) = return x
ioInterpreter (FreeMonad.Free …Run Code Online (Sandbox Code Playgroud) 我刚刚开始使用 Go,我遇到了一种情况,我需要创建一组实体,其大小/长度仅在运行时已知。我首先认为使用列表是一个不错的选择,但很快意识到切片是 Go 中惯用的数据结构。出于好奇,我写了以下基准测试
package main
import (
"container/list"
"testing"
)
var N = 10000000
func BenchmarkSlices(B *testing.B) {
s := make([]int, 1)
for i := 0; i < N; i += 1 {
s = append(s, i)
}
}
func BenchmarkLists(B *testing.B) {
l := list.New()
for i := 0; i < N; i += 1 {
l.PushBack(i)
}
}
Run Code Online (Sandbox Code Playgroud)
这给了我
BenchmarkSlices-4 2000000000 0.03 ns/op
BenchmarkLists-4 1 1665489308 ns/op
Run Code Online (Sandbox Code Playgroud)
鉴于这append将创建一个新数组,并在旧数组已满时将所有数据从旧数组复制到新数组,因此我预计列表的性能比上面示例中的切片更好。然而,我的期望显然是错误的,我正在尝试理解原因。
我编写了以下内容,以便更好地理解如何append在需要时创建新数组:
package main
import "fmt" …Run Code Online (Sandbox Code Playgroud)