如您所知,Template Haskell用于在编译时以编程方式生成各种AST拼接.
然而,拼接通常可能非常不透明,并且通常难以辨别拼接实际生成的内容.如果你运行Qmonad进行拼接,并且拼接是良好类型的,你可以很好地show表示生成的AST片段,但由于其非结构化布局,这种表示很难理解.
将TH生成的AST转换为类似于普通Haskell代码的首选方法是什么,以便可以轻松读取和理解代码?可以从例如给定Dec值重建源代码吗?是否必须阅读GHC核心代码?有没有办法至少构建AST,使其变得更具可读性(超出pretty-show包裹的范围)?
镜头似乎没有任何缺点,同时具有优于标准Haskell的显着优势:是否有任何理由我不应该尽可能使用镜头?有性能考虑吗?另外,模板Haskell是否有任何重大开销?
我正在寻找一个可用于跟踪程序进度的monad变换器.要解释如何使用它,请考虑以下代码:
procedure :: ProgressT IO ()
procedure = task "Print some lines" 3 $ do
liftIO $ putStrLn "line1"
step
task "Print a complicated line" 2 $ do
liftIO $ putStr "li"
step
liftIO $ putStrLn "ne2"
step
liftIO $ putStrLn "line3"
-- Wraps an action in a task
task :: Monad m
=> String -- Name of task
-> Int -- Number of steps to complete task
-> ProgressT m a -- Action performing the task
-> ProgressT m …Run Code Online (Sandbox Code Playgroud) monads haskell functional-programming coroutine monad-transformers
我需要以下类功能:
class InterleavedHomomorphic x where
interleaveHomomorphism :: (forall a . f a -> g a) -> x f -> x g
Run Code Online (Sandbox Code Playgroud)
显然,我为它发明的名称绝不是任何东西的官方术语,上面的类型不是很优雅.这是一个在某些库中有名称甚至实现的概念吗?有没有更合理的方法呢?
这个函数的目的是我有一些f注释一些数据的上下文(为了这个问题Foo,Bar它只是随机的示例数据结构):
data Foo f = One (f (Bar f)) | Product (f (Foo f)) (f (Foo f))
data Bar f = Zero | Succ (f (Bar f))
Run Code Online (Sandbox Code Playgroud)
我想以多态方式转换数据的上下文; 只知道上下文之间的同态,而不是(必然)关心数据本身.这可以通过提供instance InterleavedHomomorphic Foo和instance InterleavedHomomorphic Bar在上面的例子中完成.
我想使用" epoll"式事件管理实现高效的单线程套接字通信.
如果我"从头开始"编写一个非常强制性的程序,我会基本上这样做(只是一些我刚输入的伪代码 - 可能不会编译):
import Control.Concurrent
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import qualified GHC.Event as Event
import Network
import Network.Socket
import Network.Socket.ByteString
main = withSocketFromSomewhere $ \ socket -> do
let fd = fromIntegral . fdSocket $ socket
-- Some app logic
state <- newMVar "Bla"
-- Event manager
manager <- Event.new
-- Do an initial write
initialWrite socket state manager
-- Manager does its thing
Event.loop manager
write manager socket bs =
-- Should …Run Code Online (Sandbox Code Playgroud) 在某些类上下文中使用时,Newtypes通常用于更改某些类型的行为.例如,可以使用Data.Monoid.All包装器来更改Bool用作a时的行为Monoid.
我目前正在编写一个适用于各种不同类型的newtype包装器.包装器应该改变一个特定类实例的行为.它可能看起来像这样:
newtype Wrapper a = Wrapper a
instance Special a => Special (Wrapper a) where
-- ...
Run Code Online (Sandbox Code Playgroud)
但是,添加此包装器通常会改变包装类型的可用性.例如,如果我以前能够使用该函数mconcat :: Monoid a => [a] -> a,我现在无法将其用于包装值列表.
我当然可以使用-XGeneralizedNewtypeDeriving和newtype Wrapper a = Wrapper a deriving (Monoid).然而,这只能解决问题,Monoid而不是其他类,而我将处理一个充满不同类的开放世界,并且独立的孤立广义newtype派生并不是真正的实用选择.理想情况下,我想写deriving hiding (Special)(除了派生每个类Special),但当然这不是有效的Haskell.
有没有办法做到这一点,或者我只是搞砸了,需要添加GHC功能请求?
我通过以下命令在Linux上运行蓝牙RFCOMM服务:
sdptool add --channel 1 SP
rfcomm watch hci0 1 "$COMMAND" {}
# ^ here
Run Code Online (Sandbox Code Playgroud)
在$COMMAND将二进制数据写入作为参数传递的文件.我通过执行以下操作测试了它的行为:
FIFO=$(tempfile)
mkfifo "$FIFO"
"$COMMAND" "$FIFO" &
cat "$FIFO" | hexdump -C # <- output is correct
Run Code Online (Sandbox Code Playgroud)
然而,通过SPP/RFCOMM发现(UUID从不同的装置连接到服务时00001101-0000-1000-8000-00805F9B34FB),我看到的每个实例0x0A(LF)被替换为0x0D 0x0A(CR LF)中的流.问题不在接收端,因为我尝试连接到也发送二进制数据的硬件串行设备,并且转换不会发生.它必须是# ^ here执行替换的第一个片段(在行上方)中的命令.
为什么该rfcomm工具会进行此替换,如何禁用它?
使用这种GHC.Exts.Constraint类型,我有一个广义的存在量化数据结构,如下所示:
data Some :: (* -> Constraint) -> * where
Specimen :: c a => a -> Some c
Run Code Online (Sandbox Code Playgroud)
(实际上,我的类型比这更复杂;这只是一个简化的例子)
现在,让我们说我有一个函数,例如,需要Enum约束,我想要对其进行操作Some c.我需要做的是检查Enum约束是否暗示c:
succSome :: Enum ? c => Some c -> Some c
succSome (Specimen a) = Specimen $ succ a
Run Code Online (Sandbox Code Playgroud)
?在这种情况下,我如何实现运算符?可能吗?
haskell existential-type ghc type-constraints higher-rank-types
我有两个这样的JPA实体:
@Entity
class Foo {
@Id
private long id;
// ...
}
@Entity
class Bar {
@ElementCollection(targetClass = String.class, fetch = FetchType.LAZY)
@MapKeyJoinColumn(name = "foo_id", referencedColumnName = "id")
@MapKeyClass(Foo.class)
@Column(name = "content")
@CollectionTable(name = "bar_foo_content",
joinColumns = @JoinColumn(name = "bar_id", referencedColumnName = "id"))
@ManyToMany(cascade = CascadeType.ALL)
private Map<Foo, String> fooContent = Maps.newHashMap();
// ...
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该fooContent字段在Bar和之间形成了多对多关系Foo,因此我认为使用@ManyToMany该字段指定级联是合适的.但是,当尝试在地图中保留一个Bar带有几个Foo ? String值的时候,我得到以下异常:
javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through …Run Code Online (Sandbox Code Playgroud) 我正在使用STM做事,除此之外还使用了TBQueue数据结构并取得了巨大的成功.我一直在使用它的一个有用功能包括根据a中的前提条件从中读取TVar,基本上是这样的:
shouldRead <- readTVar shouldReadVar
if shouldRead
then do
a <- readTBQueue queue
doSomethingWith a
else doSomethingElse
Run Code Online (Sandbox Code Playgroud)
如果我们假设在执行此块之前它queue是空的并且shouldReadVar包含True它,那么它将导致readTBQueue调用retry,并且当shouldReadVar包含False或queue包含元素时,块将被重新执行,无论先发生什么.
我现在需要一个同步通道数据结构,类似于本文中描述的结构(如果你想理解这个问题,请阅读它),除非它需要在前一个例子中的前置条件下可读,也可能与其他东西一起构成.
让我们SyncChan用它来定义这个数据结构writeSyncChan并readSyncChan定义操作.
这是一个可能的用例:这个(伪)代码(因为我混合了STM/IO概念,所以不会起作用):
shouldRead <- readTVar shouldReadVar
if shouldRead
then do
a <- readSyncChan syncChan
doSomethingWith a
else doSomethingElse
Run Code Online (Sandbox Code Playgroud)
假设当前没有其他线程在writeSyncChan调用上阻塞,并且shouldReadChan包含True,我希望块" retry"直到shouldReadChan包含False,或者在a上包含不同的线程块 …
haskell ×8
ghc ×4
bluetooth ×1
comonad ×1
concurrency ×1
coroutine ×1
eclipselink ×1
events ×1
functor ×1
homomorphism ×1
java ×1
jpa ×1
lenses ×1
linux ×1
monads ×1
newline ×1
newtype ×1
pretty-print ×1
serial-port ×1
sockets ×1
stm ×1
transactions ×1
typeclass ×1