Haskell 列表'dist'函数的应用分发服务器
我想我从中复制了以下Haskell 列表'dist'函数的应用分发服务器,haskell,Haskell,我想我从中复制了以下dist函数: 本文以以下内容作为该功能的开头: 你注意到序列和转置现在看起来很相似吗? 区分这两个程序的细节由 从它们的类型中选择编译器。两者都是应用程序的实例 名单分发者 但是,我得到以下编译时错误: ghci> :l ApplicativePaper.hs [1 of 1] Compiling Main ( ApplicativePaper.hs, interpreted ) ApplicativePaper.hs:12:20:
dist
函数:
本文以以下内容作为该功能的开头:
你注意到序列和转置现在看起来很相似吗?
区分这两个程序的细节由
从它们的类型中选择编译器。两者都是应用程序的实例
名单分发者
但是,我得到以下编译时错误:
ghci> :l ApplicativePaper.hs
[1 of 1] Compiling Main ( ApplicativePaper.hs, interpreted )
ApplicativePaper.hs:12:20:
Could not deduce (a ~ f a)
from the context (Applicative f)
bound by the type signature for
dist :: Applicative f => [f a] -> f [a]
at ApplicativePaper.hs:10:9-39
`a' is a rigid type variable bound by
the type signature for dist :: Applicative f => [f a] -> f [a]
at ApplicativePaper.hs:10:9
Relevant bindings include
vs :: [f a] (bound at ApplicativePaper.hs:12:9)
v :: f a (bound at ApplicativePaper.hs:12:7)
dist :: [f a] -> f [a] (bound at ApplicativePaper.hs:11:1)
In the first argument of `(:)', namely `v'
In the expression: (:) v (dist vs)
Failed, modules loaded: none.
请让我知道我做错了什么。此外,请提供此函数的直观说明。在本文中,第4页上定义的双括号
〚f u1…un
与纯f u1…un
相同
文本中dist
的定义如下
dist :: Applicative f ⇒ [f a] → f [a ]
dist [] = 〚 [] 〛
dist (v : vs) = 〚 (:) v (dist vs) 〛
将其他符号翻译成Haskell,并替换〚〛
的定义,结果是
dist :: Applicative f => [f a] -> f [a ]
dist [] = pure []
dist (v : vs) = pure (:) <*> v <*> (dist vs)
dist::Applicative f=>[fa]->f[a]
dist[]=纯[]
距离(v:vs)=纯(:)v(距离vs)
错误的括号。Conor McBride和Ross Paterson使用所谓的习惯用法括号。以下是您的虚拟语法定义(但它可能是通过Strathclyde Haskell增强编译的,我不确定):
(| f x y z |)
阐述到纯f x y z
。所以dist
的定义是正确的
dist :: Applicative f => [f a] -> f [a]
dist [] = pure []
dist (v : vs) = (:) <$> v <*> dist vs -- f <$> x == pure f <*> x
只是它需要一个monad而不是applicative
还有一个dist
的泛化,由Traversable
typeclass提供:
sequenceA :: Applicative f => t (f a) -> f (t a)
所以这里有一些t
(它既是函子
又是可折叠的
),而不是[]
这是对序列的描述
-- | Evaluate each action in the sequence from left to right,
-- and collect the results.
这是非常详尽的。比如说
main = dist [print 3, print 4, print 5]
main = do
print $ dist_ [Just 3, Just 4, Just 5]
print $ dist_ [Nothing, Just 3]
印刷品
3
4
5
Just ()
Nothing
Just [3,4,5]
Nothing
由于每个monad都是一个应用程序,dist
在这里与IO monad一起正常工作。然而,没有必要在这里收集结果。这就是为什么有序列
函数,它返回()
作为结果
很容易定义距离:
dist_ :: Applicative f => [f a] -> f ()
dist_ [] = pure ()
dist_ (v : vs) = v *> dist_ vs
因此,您只需执行列表中的所有操作
比如说
main = dist [print 3, print 4, print 5]
main = do
print $ dist_ [Just 3, Just 4, Just 5]
print $ dist_ [Nothing, Just 3]
印刷品
3
4
5
Just ()
Nothing
Just [3,4,5]
Nothing
因为
Just smth1 *> Just smth2 == Just smth2
Nothing *> Just smth2 == Nothing
dist
为这一机制添加的唯一功能是收集结果
所以
印刷品
3
4
5
Just ()
Nothing
Just [3,4,5]
Nothing
另外,看一下。或简单的
dist(v:vs)=(:)v dist vs
@AaditMShah虽然这是正确的,但通过pure
的定义更为一致:用pure
提升“列表”的第一个元素,然后用
连接所有内容。那样的话,〚【】【】
是完全合理的。