我有一个有状态类型的>>和>>=运算符,几乎是一个monad.预期用途是为另一种语言生成代码,并且具有可用的标记将是非常合适的.
但是,没有明确定义的返回函数,因为值只应与副作用一起产生.因此,如果我伪造一个返回函数,return函数应该只返回一个错误,并且它违反了monad定律.(即使用返回函数永远无效.)
我观察到的是,这种说法只会使两个运算符,即运算符>>和>>=运算符.
有没有办法只为那些2个操作符保留像记号这样的东西,或者像它一样干净的东西,但没有制作monad?
注意:行下方是标题中不需要的详细信息.这就是为什么我问这个问题的背景,回答我感兴趣的问题.浏览这个主题的其他人可能更愿意忽略它.
更正:我没有将代码生成为命令式语言,尽管它无关紧要.我正在为Javascript生成代码.
澄清(响应bdonlan):我的类型是(ma),它带有一个状态(这是给定各种参数的代码,类似于状态monad)并将返回一个值(生成的代码中的变量名称) ,附有haskell类型).因此,不应该有一种方法来返回与变量名相关联的值,而不会生成定义变量名的代码.*这完全是由于我的设计,可能不如我未想到的其他设计.
回应答复:似乎有两种回应.首先,是否确实是可能的,也许是使用符号的最佳方式.第二个是关于使用monad是否更好,并定义一个返回(或者是否有意义不这样做 - 可能在以后的某个时间点,我会发现需要返回).
我要做的事情的例子:
data JsState = JsState { code :: String , vidCount :: Int }
-- vidCount is for generating unique variable names
newtype JsStmt = JsStmt ( JsState -> JsState )
newtype JsMonad a = JsMonad ( JsState -> ( a , JsState ) )
def :: (JsValue a) => a -> JsMonad a
-- Outputs "var " ++ toUniqueVarName vidCount …Run Code Online (Sandbox Code Playgroud) 我想删除if ... then ... else ...关键字,因为我在Haskell中嵌入了一个语言/ DSL.if,then并else传达了很多的意思在许多领域,这将是巨大的,如果我能重新定义(或保留未定义)它们以反映语言/域的性质.
我在Google和stackoverflow上搜索过,但一无所获.(我确实找到了一个旧线程,为什么if ... then ... else ...在Haskell中包含了关键字.)
我的IDE在Leksah中,并且,如果可以删除关键字,那么设置将if ... then ... else ...关键字更改回正常的字体/颜色/解包也是很好的.
我已经尝试过if'for 的命名约定if等等.它感觉不太好,特别是当我想定义if和if',并且必须定义if',if''而不是,if1和if2.两者的存在if',并if还可能会造成混乱.(由于DSL的用户是Haskell程序员,在我的情况下,这种混乱并不是一个严重的问题,但我认为它可以在其他情况下提供帮助).
总结迄今为止的回复:
RebindableSyntaxGHC 的扩展名.不像删除关键字那样通用:保留Haskell的if-then-else的语法.(Frerich Raabe)data Conditional b a = If b (Then a) (Else a)(仅适用于某些上下文).(CA McCann)如果RebindableSyntax是一个相对较新的特征,那么它不太可能找到更通用的方式,至少在下一版GHC之前是这样.
我目前定义任意arity函数的方法如下,A是累加器,E是输入参数类型,R是结果类型.
combine :: A -> E -> A
class X r where
foo :: A -> E -> r
instance X R where
foo :: A -> E -> R
instance X r => X ( E -> r ) where
foo :: A -> E -> E -> r
foo ( a :: A ) ( x :: E ) =
foo ( a `combine` e :: A )
doFoo = foo emptyA
Run Code Online (Sandbox Code Playgroud)
但是foo的最小arity是1.foo的最小值仍然是A - > E - > …
这个
newtype ( Show a , Show b , Show c ) => T a b c = T Int
t :: T a b c -> a -> b -> c -> String
t ( T x ) a b c = show a ++ show b ++ show c
Run Code Online (Sandbox Code Playgroud)
给我一个错误:
No instance for (Show c)
arising from a use of `show'
In the second argument of `(++)', namely `show c'
In the second argument of `(++)', namely `show …Run Code Online (Sandbox Code Playgroud) 为什么我不能这样做
z = x?
Run Code Online (Sandbox Code Playgroud)
但我可以这样做吗?
y s = x s
Run Code Online (Sandbox Code Playgroud)
我是Haskell新手这是我在GHCi中尝试过的:
Prelude> import Happstack.Server
Prelude Happstack.Server> let x s = ok $ toResponse $ "Some string"
Prelude Happstack.Server> :t x
x :: FilterMonad Response m => t -> m Response
Prelude Happstack.Server> let y s = x s
Prelude Happstack.Server> :t y
y :: FilterMonad Response m => t -> m Response
Prelude Happstack.Server> let z = x
<interactive>:1:9:
No instance for (FilterMonad Response m0)
arising from a use of …Run Code Online (Sandbox Code Playgroud) 从
http://happstack.com/docs/crashcourse/HappstackState.html
当我运行服务器时,偷看计数器增加了
相关的相关代码是:
handlers :: ServerPart Response
handlers =
msum [ dir "peek" $ do c <- query PeekCounter
ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
, do c <- update (AddCounter 1)
ok $ toResponse $ "New count is: " ++ show (unCounter c)
]
Run Code Online (Sandbox Code Playgroud)
但是,当我修改它时
handlers :: ServerPart Response
handlers =
msum [ dir "peek" $ do c <- query PeekCounter
ok $ toResponse $ "peeked at …Run Code Online (Sandbox Code Playgroud)