小编yai*_*chu的帖子

如何从模板Haskell发出重写规则

我写了一些TemplateHaskell发出重写规则的代码,但是GHC(8.6.5)拒绝了我的规则,并出现以下错误:

Rule "mapKWith/Pure":
    Illegal expression: ((mapKWith @Pure) constraintProxy)
    in left-hand side: ((mapKWith @Pure) constraintProxy) func
LHS must be of form (f e1 .. en) where f is not forall'd
Run Code Online (Sandbox Code Playgroud)

如果我使用编译-ddump-splices并查看该规则,则可以看到它看起来像这样(重新格式化):

{-# RULES "mapKWith/Pure"
    forall
    (constraintProxy :: Proxy constraint)
    (func :: forall child. constraint child => Tree m child -> Tree n child).
    ((mapKWith @Pure) constraintProxy) func =
    \case MkPure x -> MkPure (func x)
#-}
Run Code Online (Sandbox Code Playgroud)

如果我将此规则复制到代码中并进行编辑,则只需要删除LHS的多余括号,GHC就可以接受它(这样LHS就变得mapKWith @Pure constraintProxy func没有括号了)。

有没有一种方法可以从TH发出没有多余括号的代码,以便GHC可以接受它来重写规则LHS?还有其他解决方案或解决方法吗?

对于上下文,我正在尝试生成这些规则来帮助GHC内联函数获取RankNTypes值,并且我尝试的代码可在https://github.com/lamdu/syntax-tree/blob/rewrite-rules/src中 …

haskell template-haskell

14
推荐指数
0
解决办法
174
查看次数

如何避免同时处理键事件和字符事件

为了处理文本输入,我使用设置了一个char-event回调glfwSetCharCallback,并且为了处理非文本按键(箭头键和热键),我使用设置了一个键事件回调glfwSetKeyCallback

在这种情况下发生的情况是,对于一个字符键的按键操作,我收到两个调用,一个在键事件回调中,然后一个在char事件回调中。这可能会导致不想要的效果-例如,假设用户将键“ a”配置为进入文本编辑器的“附加模式”-进入模式后,它还将输入字符“ a”。处理这个?

到目前为止,我已经依赖于两个事件在glfwPollEvents返回之前一起到达,并且已经将它们合并。但是我得到报告说,该方案在某些Ubuntu系统上不能很好地工作。

glfw

12
推荐指数
1
解决办法
107
查看次数

Haskell FFI:调用FunPtrs

这是我的情况:

我想调用ffmpeg的av_free_packet函数:

// avformat.h
static inline void av_free_packet(AVPacket *pkt)
{
  if (pkt && pkt->destruct)
    pkt->destruct(pkt);
}
Run Code Online (Sandbox Code Playgroud)

但不幸的是static inline,这个功能是,因此并没有真正出现在链接库中.

但是,这是一个非常简单的功能,我可以在Haskell中重新实现.这就是我无法弄清楚该怎么做的事情.这是部分尝试(.hsc):

av_free_packet :: Ptr AVPacket -> IO ()
av_free_packet pkt =
  when (nullPtr /= pkt) $ do
    destruct <- (#peek AVPacket, destruct) pkt :: IO (FunPtr (Ptr AVPacket -> IO ()))
    when (nullFunPtr /= destruct) $ funPtrToFun destruct pkt

funPtrToFun :: FunPtr a -> a
funPtrToFun = ?
Run Code Online (Sandbox Code Playgroud)

现在我可以求助于在C中实现这个函数(通过调用原始函数),但在我看来,调用函数指针应该可能以某种方式..

c haskell ffi

10
推荐指数
2
解决办法
1598
查看次数

'在Haskell函数名中的含义?

报价'用于什么?我已经阅读了有关curried函数的内容,并阅读了两种定义add函数的方法 - curried和uncurried.咖喱版......

myadd' :: Int -> Int -> Int
myadd' x y = x + y
Run Code Online (Sandbox Code Playgroud)

......但没有引用它同样有效.那有什么意义'呢?

haskell naming-conventions

10
推荐指数
4
解决办法
2518
查看次数

有什么方法可以创建unmemo-monad?

假设某人制作了下棋或解决数独游戏的程序.在这种程序中,有一个表示游戏状态的树结构是有意义的.

这棵树非常大,"实际上是无限的".由于Haskell支持无限数据结构,因此这本身不是问题.

一个熟悉的无限数据结构示例:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)

节点仅在首次使用时分配,因此列表占用有限的内存.如果他们不保留对其头部的引用,也可以迭代无限列表,允许垃圾收集器收集其不再需要的部分.

回到树示例 - 假设一个人在树上进行一些迭代,如果仍然需要树的根,则迭代的树节点可能不会被释放(例如,在迭代加深搜索中,树将被迭代多次因此需要保留根).

我想到的这个问题的一个可能的解决方案是使用"unmemo-monad".

我将尝试使用monadic列表来演示这个monad应该做什么:

import Control.Monad.ListT (ListT)  -- cabal install List
import Data.Copointed  -- cabal install pointed
import Data.List.Class
import Prelude hiding (enumFromTo)

nums :: ListT Unmemo Int  -- What is Unmemo?
nums = enumFromTo 0 1000000

main = print $ div (copoint (foldlL (+) 0 nums)) (copoint (lengthL nums))
Run Code Online (Sandbox Code Playgroud)

使用时nums :: [Int],程序会在迭代nums过程中需要大量内存作为参考.lengthL numsfoldlL (+) 0 nums

目的 …

performance haskell

10
推荐指数
1
解决办法
432
查看次数

这种类型类约束是必要的还是多余的?

以下代码成功编译,但在使用 GHC 9.2.3 时收到警告-Wredundant-constraints

\n
{-# LANGUAGE UndecidableInstances, FlexibleInstances #-}\n\nclass Functor f => C f where c :: f Int\n\ninstance (Functor f, Applicative f) => C f where c = pure 42\n
Run Code Online (Sandbox Code Playgroud)\n

由此产生的警告:

\n
test.hs:5:10: warning: [-Wredundant-constraints]\n    \xe2\x80\xa2 Redundant constraint: Functor f\n    \xe2\x80\xa2 In the instance declaration for \xe2\x80\x98C f\xe2\x80\x99\n  |\n5 | instance (Functor f, Applicative f) => C f where c = pure 42\n  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果我删除此约束,代码将不再进行类型检查:

\n
test.hs:5:10: error:\n    \xe2\x80\xa2 Could not deduce (Functor …
Run Code Online (Sandbox Code Playgroud)

haskell typeclass ghc

10
推荐指数
1
解决办法
217
查看次数

Haskell:重叠实例

请考虑以下示例程序:

next :: Int -> Int
next i
  | 0 == m2 = d2
  | otherwise = 3 * i + 1
  where
    (d2, m2) = i `divMod` 2

loopIteration :: MaybeT (StateT Int IO) ()
loopIteration = do
  i <- get
  guard $ i > 1
  liftIO $ print i
  modify next

main :: IO ()
main = do
  (`runStateT` 31) . runMaybeT . forever $ loopIteration
  return ()
Run Code Online (Sandbox Code Playgroud)

它只能使用get而不是lift get因为instance MonadState s m …

haskell typeclass

9
推荐指数
2
解决办法
4842
查看次数

是"特定于"基础:GHC.Base.Monad"吗?

认为标准Monad类有缺陷并且它应该实际扩展FunctorPointed浮动的想法.

我不一定声称这是正确的做法,但假设有人试图这样做:

import Prelude hiding (Monad(..))

class Functor m => Monad m where
    return :: a -> m a
    join :: m (m a) -> m a
    join = (>>= id)
    (>>=) :: m a -> (a -> m b) -> m b
    a >>= t = join (fmap t a)
    (>>) :: m a -> m b -> m b
    a >> b = a >>= const b
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利,但在尝试使用do-notation时:

whileM :: Monad m …
Run Code Online (Sandbox Code Playgroud)

monads haskell ghc

9
推荐指数
1
解决办法
433
查看次数

神秘的cabal-install问题

干净安装"Haskell平台".(OS X Snow-Leopard&Platform 2010.1.0.1),这样做会导致简单的序列导致非常奇怪的cabal install行为:

$ cabal install time

$ cabal install random

$ ghc-pkg list random
/Library/Frameworks/GHC.framework/Versions/612/usr/lib/ghc-6.12.1/package.conf.d
   random-1.0.0.2
/Users/yairc/.ghc/i386-darwin-6.12.1/package.conf.d
   random-1.0.0.2
Run Code Online (Sandbox Code Playgroud)

random-1.0.0.2在我的系统中安装了两次.现在每次都要cabal install random重新安装random-1.0.0.2.

看起来random取决于time,并且cabal想要在有新版本time可用之后重新安装它?而且由于两个random-1.0.0.2阴谋混淆并总是认为它不是最新的,因为它正在看第一个?

ghc-pkg check 发现没有错误.

haskell cabal hackage cabal-install

9
推荐指数
2
解决办法
2430
查看次数

表达无限种类

在Haskell中表达无限类型时:

f x = x x -- This doesn't type check
Run Code Online (Sandbox Code Playgroud)

可以使用a newtype来做到这一点:

newtype Inf = Inf { runInf :: Inf -> * }

f x = x (Inf x)
Run Code Online (Sandbox Code Playgroud)

是否存在newtype允许表达无限种类的等价物?

我已经发现我可以使用类型族来获得类似的东西:

{-# LANGUAGE TypeFamilies #-}
data Inf (x :: * -> *) = Inf
type family RunInf x :: * -> *
type instance RunInf (Inf x) = x
Run Code Online (Sandbox Code Playgroud)

但是我对这个解决方案不满意 - 不同于类型的类型,Inf不会创造一种新类型(Inf x有类型*),所以安全性较低.

这个问题有更优雅的解决方案吗?

haskell types type-families type-kinds

9
推荐指数
2
解决办法
147
查看次数