处理类型族时,使用等式约束通常很方便,以避免在签名中重复某个类型函数的名称:
class Foo f where
type BulkyAssociatedType f :: *
foo :: BulkyAssociatedType f -> f
...
bar :: forall m f b .
( Monad m, Foo f, b ~ BulkyAssociatedType f
, Monoid b, Monoid (m b)
) => f -> m f
Run Code Online (Sandbox Code Playgroud)
即使缩写没有在签名本身中出现,只有在约束中才有效.
有了课程,这显然是不可能的;
class ( Foo f, b ~ BulkyAssociatedType f, Monoid b, ...) => Bar f
Run Code Online (Sandbox Code Playgroud)
抱怨类型变量b不在范围内.
有一些方法可以实现类似的东西,避免一点点重复 - 样板吗?
解决“ f = f(<*>)pure”类型提示了这一点,该类型讨论了一个更复杂的示例,但该示例也有效。
以下定义可以毫无问题地进行编译:
w :: Integral a => a
w = fromInteger w
Run Code Online (Sandbox Code Playgroud)
...当然,它在运行时无法正常工作,但这是个问题。问题的关键是,定义w本身使用的专用版本的w :: Integer。显然,这是一个合适的实例,因此进行类型检查。
但是,如果我们删除签名,那么GHC不会推断上述类型,而只能推断具体类型:
w' = fromInteger w'
Run Code Online (Sandbox Code Playgroud)
GHCi> :t w
w :: Integral a => a
GHCi> :t w'
w' :: Integer
Run Code Online (Sandbox Code Playgroud)
好吧,当我看到这一点时,我相当确定这是工作中的单态性限制。众所周知,例如
i = 3
Run Code Online (Sandbox Code Playgroud)
GHCi> :t i
i :: Integer
Run Code Online (Sandbox Code Playgroud)
虽然i :: Num p => p完全有可能。实际上,i :: Num p => p 可以推断出是否-XNoMonomorphismRestriction处于活动状态,即是否禁用了单态性限制。
但是,即使禁用了单态性限制, …
我们如何证明continuation monad没有有效的实例MonadFix?
在GHC中编译此程序时:
import Control.Monad
f x = let
g y = let
h z = liftM not x
in h 0
in g 0
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
test.hs:5:21:
Could not deduce (m ~ m1)
from the context (Monad m)
bound by the inferred type of f :: Monad m => m Bool -> m Bool
at test.hs:(3,1)-(7,8)
or from (m Bool ~ m1 Bool, Monad m1)
bound by the inferred type of
h :: (m Bool ~ m1 Bool, Monad m1) => t1 …Run Code Online (Sandbox Code Playgroud) 假设我想用语言X解析文件.真的,我只对其中的一小部分信息感兴趣.为此目的在Haskell的许多eDSL中编写解析器很容易(例如Megaparsec).
data Foo = Foo Int -- the information I'm after.
parseFoo :: Parsec Text Foo
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)
这很容易产生一种功能getFoo :: Text -> Maybe Foo.
但现在我还要修改信息的来源Foo,即基本上我想实现
changeFoo :: (Foo -> Foo) -> Text -> Text
Run Code Online (Sandbox Code Playgroud)
与属性
changeFoo id ? id
getFoo . changeFoo f ? fmap f . getFoo
Run Code Online (Sandbox Code Playgroud)
可以通过将解析器的结果更改为类似镜头的方式来实现
parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...
Run Code Online (Sandbox Code Playgroud)
但是这使定义变得更加麻烦 - 我不能仅仅string掩盖不相关的信息,而是需要存储每个subparse 的匹配并手动重新组装它.
这可以通过将字符串重组保持在StateT解析器monad周围的层中来实现自动化,但我不能只使用现有的原始解析器.
这个问题是否有现成的解决方案?
下列
(&&) :: Bool -> Bool -> Bool
False && _ = False
True && False = False
True && True = True
Run Code Online (Sandbox Code Playgroud)
具有所需的短路特性False && undefined ? False.第一个子句在右边的参数中是非严格的,保证在尝试任何其他操作之前进行检查.
显然,如果我改变顺序甚至不发布功能,它仍然有效
both :: (Bool,Bool) -> Bool
both (True,False) = False
both (True, True) = True
both (False, _) = False
Prelude> both (False, undefined)
False
Run Code Online (Sandbox Code Playgroud)
但这实际上是由标准保证的吗?与条款的顺序不同,模式的评估顺序在这里并不十分清楚.在确定snd元素之前,我是否可以确定匹配(True,False)将在(False,_)确定后立即中止?
为了说清楚,我不是在谈论自由monad看起来很像一个应用于仿函数的固定点组合器,即Free f基本上是一个固定点f.(不是说这不好玩!)
我正在谈论的是固定点Free, Cofree :: (*->*) -> (*->*),即仿函数f,使得Free f同构于f自身.
背景:今天,坚定了我对自由的单子,而缺乏把握,我决定只写了他们的出来不同的简单仿函数,既为Free与对Cofree,看看有什么更好的知名[合作]单子他们会在同构.是什么吸引了我特别的是发现那Cofree Empty是同构的Empty(意思是,Const Void的任何类型映射到无人居住的仿函数).好吧,也许这只是愚蠢 - 我发现如果你把空垃圾放进去,你就会把空垃圾拿出来,是的! - 但是,嘿,这是类别理论,整个宇宙从看似琐碎的事物中崛起......对吧?
当前的问题是,如果Cofree有这样一个固定点,那又怎么样Free?嗯,它当然不能是Empty那不是一个单子.快速嫌疑人将附近的东西像Const ()或者Identity,但没有:
Free (Const ()) ~~ Either () ~~ Maybe
Free Identity ~~ (Nat,) ~~ Writer Nat
Run Code Online (Sandbox Code Playgroud)
实际上,Free总是添加额外构造函数的事实表明,任何一个固定点的仿函数的结构必须已经是无限的.但似乎奇怪的是,如果Cofree有这样一个简单的定点,Free应该只有一个更复杂的定义点(就像FixFree a = …
对于不确定性传播Approximate类型,我想要Functor通过实例Monad.然而,这不起作用,因为我需要在包含的类型上使用向量空间结构,因此它实际上必须是类的受限版本.由于仍有似乎并不为那些标准库(或者是那里?请点我.还有rmonad,但它使用*,而不是Constraint作为上下文样,这似乎只是过时的我),我写我自己的版本的暂时的.
这一切都很容易 Functor
class CFunctor f where
type CFunctorCtxt f a :: Constraint
cfmap :: (CFunctorCtxt f a, CFunctorCtxt f b) => (a -> b) -> f a -> f b
instance CFunctor Approximate where
type CFunctorCtxt Approximate a = FScalarBasisSpace a
f `cfmap` Approximate v us = Approximate v' us'
where v' = f v
us' = ...
Run Code Online (Sandbox Code Playgroud)
但是直接翻译Applicative,就像
class CFunctor …Run Code Online (Sandbox Code Playgroud) 显然有点心不在焉,我写了类似下面的内容:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
class Foo f where
type Bar f :: *
retbar :: Bar f -> IO f
type Baz f = (Foo f, Eq f)
-- WithBar :: * -> (*->Constraint) -> * -> Constraint
type WithBar b c f = (c f, Bar f ~ b)
instance Foo () where
type Bar () = ()
retbar = return
naim :: WithBar () Baz u => IO u -- why …Run Code Online (Sandbox Code Playgroud) 虽然沉思什么更有用的标准类建议这一个
class Coordinate c where
createCoordinate :: x -> y -> c x y
getFirst :: c x y -> x
getSecond :: c x y -> y
addCoordinates :: (Num x, Num y) => c x y -> c x y -> c x y
Run Code Online (Sandbox Code Playgroud)
它发生我,而不是其他VectorSpace-y或者R2,一个较为普遍的野兽可能潜伏在这里:一Type -> Type -> Type,其两个包含类型都可以提取.嗯,也许他们可以extract编辑?
事实证明,comonad也没有bifunctors包含一些叫做的东西Bicomonad.问题是,从理论上讲,这类课程是否有意义?不像Bimonad(也没有定义,我真的不知道怎么看),一个天真的定义似乎是合理的:
class Bifunctor c => Bicomonad c where
fst :: …Run Code Online (Sandbox Code Playgroud) haskell ×10
applicative ×1
bifunctor ×1
bijection ×1
comonad ×1
continuation ×1
free-monad ×1
monadfix ×1
monads ×1
parsec ×1
parsing ×1
recursion ×1
strictness ×1
typeclass ×1