Haskell中的一个常见习语(差异列表)是将列表表示xs为值(xs ++).然后(.)变成" (++)"并id变成" []"(实际上这适用于任何幺半群或类别).由于我们可以在恒定时间内组合函数,因此这为我们提供了一种通过追加来有效构建列表的好方法.
不幸的是,类型[a] -> [a]比表单的函数类型更大(xs ++)- 列表上的大多数函数除了在它们的参数之前做一些事情.
解决此问题的一种方法(如用于dlist)是DList使用智能构造函数创建一个特殊类型.另一种方法(如所使用的ShowS)是不在任何地方强制执行约束并希望最好.但是有一种很好的方法可以保持差异列表的所有所需属性,同时使用一个完全正确大小的类型吗?
solrize在#haskell问了一个关于这个代码的一个版本的问题,我尝试了其他一些案例,并且想知道发生了什么.在我的机器上,"快速"代码需要大约1秒钟,而"慢速"代码需要大约1.3-1.5(所有内容都被编译ghc -O2).
import Data.List
log10 :: Double -> Double
--log10 x = log x / log 10 -- fast
--log10 = logBase 10 -- slow
--log10 = barLogBase 10 -- fast
--log10 = bazLogBase 10 -- fast
log10 = fooLogBase 10 -- see below
class Foo a where
fooLogBase :: a -> a -> a
instance Foo Double where
--fooLogBase x y = log y / log x -- slow
fooLogBase x = let lx = log …Run Code Online (Sandbox Code Playgroud) (对于以下内容,简化Show和Read解决
class Show a where show :: a -> String
class Read a where read :: String -> a
Run Code Online (Sandbox Code Playgroud)
并假设read永远不会失败.)
众所周知,人们可以制作一种存在主义的形式
data ShowVal where
ShowVal :: forall a. Show a => a -> ShowVal
Run Code Online (Sandbox Code Playgroud)
然后构建一个"异构列表" :: [ShowVal],例如
l = [ShowVal 4, ShowVal 'Q', ShowVal True]
Run Code Online (Sandbox Code Playgroud)
众所周知,这是相对无用的,因为相反,人们可以构建一个列表:: [String],例如
l = [show 4, show 'Q', show True]
Run Code Online (Sandbox Code Playgroud)
这是完全同构的(毕竟,唯一可以做的
ShowVal就是show它).
懒惰使得这个特别好,因为对于列表中的每个值,结果show都是自动记忆的,因此不会String多次计算(并且String根本不计算未使用的s).
A ShowVal等同于存在元组exists …