Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 涵盖升级数据类型的所有情况_Haskell_Data Kinds - Fatal编程技术网

Haskell 涵盖升级数据类型的所有情况

Haskell 涵盖升级数据类型的所有情况,haskell,data-kinds,Haskell,Data Kinds,因此,我最近想出了一个好主意,希望在严格和懒惰的Statetransformer模块之间共享代码: {-# LANGUAGE FlexibleInstances, DataKinds, KindSignatures #-} module State where data Strictness = Strict | Lazy newtype State (t :: Strictness) s a = State (s -> (s, a)) returnState :: a -> S

因此,我最近想出了一个好主意,希望在严格和懒惰的
State
transformer模块之间共享代码:

{-# LANGUAGE FlexibleInstances, DataKinds, KindSignatures #-}
module State where

data Strictness = Strict | Lazy
newtype State (t :: Strictness) s a = State (s -> (s, a))

returnState :: a -> State t s a
returnState x = State $ \s -> (s, x)

instance Monad (State Lazy s) where
  return = returnState
  State ma >>= amb = State $ \s -> case ma s of
    ~(s', x) -> runState (amb x) s'

instance Monad (State Strict s) where
  return = returnState
  State ma >>= amb = State $ \s -> case ma s of
    (s', x) -> runState (amb x) s'

get :: State t s s
get = State $ \s -> (s, s)

put :: s -> State t s ()
put s = State $ \_ -> (s, ())
您可以看到,
get
put
在严格类型和惰性类型上都没有任何重复,没有类型类实例,没有任何内容。然而,尽管我介绍了两种可能的
严格性
,但通常我没有
状态ts a的Monad实例:

-- from http://blog.melding-monads.com/2009/12/30/fun-with-the-lazy-state-monad/
pro :: State t [Bool] ()
pro = do
  pro
  s <- get
  put (True : s)

-- No instance for (Monad (State t [Bool])) arising from a do statement
然后我可以在
Lazy
Strict
处实例化
t
,然后运行结果并得到我期望的结果。但我为什么要给出这样的背景呢?这是一个概念上的限制,还是一个实际的限制?有什么原因我不知道为什么
Monad(State ts a)
实际上不成立,还是还没有办法说服GHC

(旁白:使用上下文
Monad(状态ts)
不起作用:

无法推断do语句产生的(Monad(State t[Bool])
来自上下文(Monad(State ts))


这让我更加困惑。肯定前者可以从后者中推断出来吗?

这是一个限制,但有一个很好的理由:如果它不这样工作,它的预期语义会是什么

runState :: State t s a -> s -> (s,a)
runState (State f) s = f s

example :: s -> a
example = snd $ runState ((State undefined) >> return 1) ()
嗯,可能是这样

example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
        = snd $ runState (State $ \s -> case undefined s of (s',_) -> (s',1)) ()
        = snd $ case undefined () of (s',_) -> (s',1)
        = snd $ case undefined of (s',_) -> (s',1)
        = snd undefined
        = undefined
example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
        = snd $ runState (State $ \s -> case undefined s of ~(s',_) -> (s',1)) ()
        = snd $ case undefined () of ~(s',_) -> (s',1)
        = snd $ (undefined,1)
        = 1
也可能是

example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
        = snd $ runState (State $ \s -> case undefined s of (s',_) -> (s',1)) ()
        = snd $ case undefined () of (s',_) -> (s',1)
        = snd $ case undefined of (s',_) -> (s',1)
        = snd undefined
        = undefined
example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
        = snd $ runState (State $ \s -> case undefined s of ~(s',_) -> (s',1)) ()
        = snd $ case undefined () of ~(s',_) -> (s',1)
        = snd $ (undefined,1)
        = 1
这些不一样。一种选择是定义一个额外类的函数,如

class IsStrictness t where
   bindState :: State t s a -> (a -> State t s b) -> State t s b
然后定义

instance IsStrictness t => Monad (State t s) where
   return = returnState
   (>>=) = bindState
您可以使用单例,而不是将
bindState
定义为
isstrictity
的一部分

data SingStrictness (t :: Strictness) where
   SingStrict :: SingStrictness Strict
   SingLazy   :: SingStrictness Lazy

class IsStrictness t where
   singStrictness :: SingStrictness t

bindState :: IsStrictness t => State t s a -> (a -> State t s b) -> State t s b
bindState ma' amb' = go singStrictness ma' amb' where
  go :: SingStrictness t -> State t s a -> (a -> State t s b) -> State t s b
  go SingStrict ma amb = ...
  go SingLazy ma amb = ...
使用GHC 7.6中的singleton基础设施,而不是自定义类和singleton类型,可以进一步增强这一功能。你最终会得到

instance SingI t => Monad (State t s)
这真的没那么可怕。习惯于约束集中有大量的
信号。至少在一段时间内,这就是它的工作方式,这不是很难看吗


至于为什么
状态t[Bool]
不能从
状态ts
中推断:问题是
状态ts
在您的顶层上下文中,这意味着
s
在最外层被量化。您正在定义一个函数,该函数表示“对于任何t和s,Monad(状态TS)我将给您…”。但是,这并不是说“对于任何这样的单子(状态t[Bool]),我会给你……”。不幸的是,这些普遍量化的约束在Haskell中并不容易

这确实是
数据种类的一个限制。我看到了一些相关的事情发生,GHC无法找出带有
数据类型的GADT的模式是详尽的,并且它产生了不会进行类型检查的建议。我满足于
示例
此时的反应,带有一个模棱两可的类型错误——意识到不管模棱两可如何解决,出现了一个
Monad
实例。它似乎是一个类型变量
t::Strictness
可以保存值
Strict
Lazy
,或者两者都不能。不过,我明白你关于
状态ts
的观点,谢谢。似乎应该有一种方式来表达普遍的约束。