小编Pet*_*lák的帖子

为什么归纳数据类型禁止类型如`data Bad a = C(Bad a - > a)`其中类型递归发生在 - >?之前?

关于归纳数据类型和模式匹配的 Agda手册:

为确保正常化,归纳事件必须出现在严格的正位置.例如,不允许以下数据类型:

data Bad : Set where
  bad : (Bad ? Bad) ? Bad
Run Code Online (Sandbox Code Playgroud)

因为构造函数的参数中存在负面的Bad.

为什么归纳数据类型需要此要求?

haskell y-combinator recursive-datastructures algebraic-data-types agda

16
推荐指数
2
解决办法
958
查看次数

如何正确使用GHC的SPECIALIZE pragma?(示例:使用Identity专门化来自monadic的纯函数.)

举个例子,假设我想在列表上写一个monadic和非monadic地图.我将从monadic开始:

import Control.Monad
import Control.Monad.Identity

mapM' :: (Monad m) => (a -> m b) -> ([a] -> m [b])
mapM' _ [] = return []
mapM' f (x:xs) = liftM2 (:) (f x) (mapM f xs)
Run Code Online (Sandbox Code Playgroud)

现在我想重用代码来编写纯map(而不是重复代码):

map' :: (a -> b) -> ([a] -> [b])
map' f = runIdentity . mapM' (Identity . f)
Run Code Online (Sandbox Code Playgroud)

什么是必要的,使map'优化的,如果它被明确地写的map特别是:

  1. 是否有必要写

    {-# SPECIALIZE mapM' :: (a -> Identity b) -> ([a] -> Identity [b]) #-} …
    Run Code Online (Sandbox Code Playgroud)

optimization haskell ghc explicit-specialization

16
推荐指数
1
解决办法
1064
查看次数

如何添加仅缓存ADT的字段?

通常我需要向ADT添加字段,只记忆一些冗余信息.但我还没有完全弄清楚如何做得好而有效.

显示问题的最佳方法是举个例子.假设我们正在使用无类型的lambda术语:

type VSym = String

data Lambda = Var VSym 
            | App Lambda Lambda
            | Abs VSym Lambda
Run Code Online (Sandbox Code Playgroud)

有时我们需要计算一个术语的自由变量集:

fv :: Lambda -> Set VSym
fv (Var v)    = Set.singleton v
fv (App s t)  = (fv s) `Set.union` (fv t)
fv (Abs v t)  = v `Set.delete` (fv t)
Run Code Online (Sandbox Code Playgroud)

很快我们意识到重复计算fv是我们应用的瓶颈.我们想以某种方式将它添加到数据类型中.喜欢:

data Lambda1 = Var (Set VSym) VSym
             | App (Set VSym) Lambda Lambda
             | Abs (Set VSym) VSym Lambda
Run Code Online (Sandbox Code Playgroud)

但它使定义相当丑陋.几乎(Set VSym)比其他所有人都占用更多的空间.而且,它在所有使用的函数中打破了模式匹配Lambda.更糟糕的是,如果我们后来决定添加一些其他的memoizing字段,我们将不得不再次重写所有模式.

如何设计一个通用的解决方案,允许轻松,不引人注意地添加这些记忆字段? …

caching haskell design-patterns memoization algebraic-data-types

16
推荐指数
1
解决办法
469
查看次数

如果thunk导致异常,那么异常是否仍然是thunk的结果?

我创建了这个小程序,它创建了一个长时间运行的thunk,最终因异常而失败.然后,多个线程尝试评估它.

import Control.Monad
import Control.Concurrent
import Control.Concurrent.MVar

main = do
    let thunk = let p = product [1..10^4]
                 in if p `mod` 2 == 0 then error "exception"
                                      else ()
    children <- replicateM 2000 (myForkIO (print thunk))
    mapM_ takeMVar children

-- | Spawn a thread and return a MVar which can be used to wait for it.
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
     mvar <- newEmptyMVar
     forkFinally io (\_ -> putMVar mvar ())
     return …
Run Code Online (Sandbox Code Playgroud)

haskell exception lazy-evaluation thunk

16
推荐指数
1
解决办法
487
查看次数

是否可以比较两种类型,如果一种可以从另一种分配?

假设我有两种类型:

t1 <- [t| (Functor f) => (a -> b) -> f a -> f b |]
t2 <- [t| (Int -> Char) -> [Int] -> [Char] |]
Run Code Online (Sandbox Code Playgroud)

是否有可能在Template Haskell中确定表达式t1也可以是t2?(我自己没有实现类型统一.)

haskell types type-conversion template-haskell

16
推荐指数
1
解决办法
353
查看次数

我应该使用新的Haskell语言扩展来支持旧的吗?

在启动一个新的Haskell项目时,它需要新旧扩展提供的语言功能,我应该使用哪些?新的还是旧的?例如:

我倾向于新的,因为他们感觉更清洁,并且他们以统一的方式为语言添加更多功能.但是,较旧的编译器支持它们,它们在现有的库中使用,也许在程序员中更为人所知.

更新:如答案/评论中所述,上述"取代"关系并不完全准确.但是,我对(经常发生的)案例感兴趣,因为几个扩展可以很好地完成任务.

language-features haskell functional-programming

15
推荐指数
2
解决办法
614
查看次数

了解scala的_ vs Any/Nothing

如果一个类有一个可变类型参数,例如Iterable[+A],声明之间是否有任何区别

def foo(bar: Iterable[_])
Run Code Online (Sandbox Code Playgroud)

def foo(bar: Iterable[Any])
Run Code Online (Sandbox Code Playgroud)


如果一个类具有逆变类型参数,例如Growable[-A],声明之间是否有任何区别

def foo(bar: Growable[_])
Run Code Online (Sandbox Code Playgroud)

def foo(bar: Growable[Nothing])
Run Code Online (Sandbox Code Playgroud)

type-systems scala wildcard covariance contravariance

15
推荐指数
1
解决办法
848
查看次数

是否使用以"_"(下划线)开头的模式名称来记录/鼓励/可移植的忽略结果?

假设我想在do-notation块中分叉一个线程,但我不关心线程id.如果我写

forkIO action
Run Code Online (Sandbox Code Playgroud)

GHC发出警告

警告:do-not语句丢弃了类型的结果ThreadId.说出这个警告

_ <- forkOS action
Run Code Online (Sandbox Code Playgroud)

这是一个好主意,因为我想表明该程序正在丢弃某些结果.但是,这样一来,丢弃的东西就不明显了.我可以写

threadId <- forkIO action
Run Code Online (Sandbox Code Playgroud)

但后来我们隐瞒了我们不会threadId在任何地方使用的事实,GHC正确警告

警告:已定义但未使用: threadId

似乎前置下划线解决了这两个问题:

_threadId <- forkIO action
Run Code Online (Sandbox Code Playgroud)

我的问题是:根据Haskell的语言规范,使用以下划线开头的变量是合法的吗?它有多便携?它在某处记录了吗?是否鼓励这样的案例 - 记录结果被忽略?

syntax portability haskell wildcard pattern-matching

15
推荐指数
1
解决办法
1714
查看次数

15
推荐指数
1
解决办法
676
查看次数

从Data.Data.Data了解gfoldl的类型签名

Data定义为其核心功能之一gfoldl:

gfoldl
  :: (Data a)
  => (forall d b. Data d => c (d -> b) -> d -> c b) 
  -> (forall g. g -> c g)   
  -> a  
  -> c a
Run Code Online (Sandbox Code Playgroud)

有什么目的cc (d -> b)它吗?为什么它不仅仅是一个常规的折叠,类似于

gfoldl'
  :: (Data a)
  => (forall d. Data d => r -> d -> r)
  -> r
  -> a  
  -> r
Run Code Online (Sandbox Code Playgroud)

haskell types type-signature scrap-your-boilerplate

15
推荐指数
1
解决办法
440
查看次数