可穿纸在第18-19页给出了一个例子,它融合了一元论和一元遍历,这听起来很有趣,但我对他们的LaTex感到困惑。
cciBody :: Char -> Count a
wciBody :: Char -> (|M| (State Bool) DotInASquare Count) a
其惊人的结果是:
(traverse cciBody) xInACircle (traverse wciBody)
与以下相同:
traverse (cciBody xInACircle wciBody)
我认为这种结果是:
Count XInASquare (|M| (State Bool) DotInASquare Count) [a]
但不是百分之百确定。会说Emoji语言的人能告诉我在Haskell应该怎么看吗?
更新
我认为xInACircle可能是一个infix sequenceA
。这种类型是匹配的。或者可能只是(,)
,它是Traversable
的一个实例。这绝对不是<*>
,尽管结果看起来有点像t (x <*> y) = t x <*> t y
,但是在论文中,他们并没有为<*>
使用展翅。
更新2
xInACircle的类型是(函子m,函子n)⇒(a→m b)→(a→n b)→(a→(m XInASquare n) b)。让你想起什么了吗?不是我。
发布于 2014-10-29 21:29:21
您对类型签名中使用的运算符感到困惑。基本上,Haskell语法中相同的规则适用于这些:第一优先级是括号,第二优先级是“应用程序”,最后优先级是“运算符”。就像你写的一样:
f 3 + g 4
在数学术语中,我们以f(3) + g(4)的形式编写,在Haskell中有一个标志来启用以冒号开头的infix类型操作符(-XTypeOperators
),这样您就可以编写类似于f :: a :* b -> b :* [a]
的表达式,而不是f :: Star a b -> Star b [a]
。它只是至少有两个参数的参数类型构造函数的另一种语法。(我想,由于->
已经是一个infix类型的构造函数,这几乎不是新闻。)我们也可以将它们写成Comp a b
和Prod a b
。
向上箭头和向下箭头是在论文中定义为类型类的一部分的函数,但我不喜欢Haskell真正接受这些函数所需要的所有语用,所以我将在下面的代码中解释它们。下面是使用Comp
和Prod
而不是它们的运算符作为有效Haskell文件的所有相关定义:
import Control.Applicative (Applicative, (<$>), (<*>), pure, WrappedMonad(..), Const(..))
import Data.Traversable (traverse)
import Control.Monad.State.Lazy (State, state, runState)
import Data.Char (isSpace)
import Data.Monoid (Monoid(..))
instance Monoid Integer where
mempty = 0
mappend = (+)
-- chained functors
newtype Comp m n a = Comp {runComp :: m (n a)}
instance (Functor m, Functor n) => Functor (Comp m n) where
fmap f = Comp . fmap (fmap f) . runComp
instance (Applicative m, Applicative n) => Applicative (Comp m n) where
pure = Comp . pure . pure
Comp mnf <*> Comp mnx = Comp ((<*>) <$> mnf <*> mnx)
-- outer product of functors
data Prod m n a = Prod {pfst :: m a, psnd :: n a}
instance (Functor m, Functor n) => Functor (Prod m n) where
fmap f (Prod ma na) = Prod (fmap f ma) (fmap f na)
instance (Applicative m, Applicative n) => Applicative (Prod m n) where
pure x = Prod (pure x) (pure x)
Prod mf nf <*> Prod mx nx = Prod (mf <*> mx) (nf <*> nx)
-- page 19,20
type Count = Const Integer
count :: a -> Count b
count _ = Const 1
cciBody :: Char -> Count a
cciBody = count
cci :: String -> Count [a]
cci = traverse cciBody
test :: Bool -> Integer
test b = if b then 1 else 0
lciBody :: Char -> Count a
lciBody c = Const (test (c == '\n'))
lci :: String -> Count [a]
lci = traverse lciBody
wciBody :: Char -> Comp (WrappedMonad (State Bool)) Count a
wciBody c = Comp (fmap Const (WrapMonad $ state $ updateState c)) where
updateState :: Char -> Bool -> (Integer, Bool)
updateState c w = let s = not (isSpace c) in (test (not w && s), s)
wci :: String -> Comp (WrappedMonad (State Bool)) Count [a]
wci = traverse wciBody
runWci :: String -> Integer
runWci s = fst $ runState (fmap getConst $ unwrapMonad $ runComp $ wci s) False
如果您不清楚从哪里来的函数,我会将导入限制在顶部,所以在那里查找(或者使用Hoogle)找到它们的定义。
您所调用的运算符 xInACircle
是一个运算符,它接受a -> m b
和a -> n b
并生成函数a -> Prod m n b
。此产品类型同时包含应用程序m
和n
的结果。一旦你理解了x-in-a-方型,你就会明白x-in-a-a-a运算符。与(Monoid m) => Applicative ((,) m)
实例不同,在第二个参数中只有fmap
s和<*>
s,两个抽象函子的Prod
是一对函子,fmap
和<*>
对这两个参数都是。这是一对(m a, n a)
,其中m
和n
都是可应用的。
https://stackoverflow.com/questions/26636328
复制相似问题