小编Chr*_*ner的帖子

遍历'过滤'的最后一个元素

我想过滤遍历,然后选择要使用的最后一个元素over.

像这样的东西(但实际上会编译):

[1,2,3,4] & traverse . filtered even . _last +~ 10
> [1,2,3,14]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

PS我知道filtered只有在不影响遍历中的元素数量时才有效.

我正在执行的实际用例是仅选择uniplate与某个谓词匹配的递归遍历的最低级别; 如果你对如何做到这一点有其他想法,我很乐意听到它们!

haskell haskell-lens

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

哪种代数模式适合这种类型的树?

我有一个谜题,

我设法编写了一些使用递归方案来做这些事情的代码,但它非常混乱,这通常意味着我在某个地方错过了一个有用的抽象.

我正在为我的文本编辑器设计一个布局系统 Rasa; 它使用与Vim非常相似的方式进行拆分.我决定使用树来描述分裂; 您可以将它想象为垂直或水平分割的二叉树,在叶节点处具有"视图".这张照片 可能有帮助.

这是我的初始数据结构:

data Direction = Hor | Vert
data Tree a = 
  Branch Direction (Tree a) (Tree a)
  | Leaf a
  deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

我需要的一些操作是:

  • split :: (View -> Tree View) -> Tree View -> Tree View 将节点(或不是)水平或垂直地分成两个节点(同时保持它们在树中的位置)
  • close :: (View -> Bool) -> Tree View -> Tree View 通过从树中删除它们并正确地重新组织相邻视图来"关闭"与谓词匹配的任何视图.
  • fmap; 我希望树能成为一个仿函数,所以我可以改变观点.

一些很好的功能: - focusRight :: Tree View -> Tree View,当且仅当左边最近的水平连接视图WAS处于活动状态时,才将视图设置为活动状态

我正在寻找一个抽象或一组抽象,以一种干净的方式提供这种功能.到目前为止,这是我的思考过程:

起初我以为我有一个Monoid,标识是空树, mappend只是将另一个分支附加到树上,但这不起作用,因为我有两个操作:垂直追加和水平追加,操作不是关联的当他们混在一起的时候.

接下来我想'我的一些操作取决于他们的背景'所以我可能有一个Comonad.我拥有的树的版本不能作为共同monad工作,因为我没有extract分支上的值,所以我重构了我的树,如下所示:

data Tree a …
Run Code Online (Sandbox Code Playgroud)

monads haskell comonad

8
推荐指数
1
解决办法
223
查看次数

"共享"或"缓存"仅由不明确的类型参数化的表达式?

我有一个棘手的问题;

所以,我知道GHC将"缓存"(缺乏一个更好的术语)顶级定义,只计算一次,例如:

myList :: [Int]
myList = fmap (*10) [0..10]
Run Code Online (Sandbox Code Playgroud)

即使我myList在几个地方使用,GHC注意到该值没有参数,因此它可以共享它并且不会"重建"列表.

我想这样做,但计算依赖于类型级上下文; 一个简单的例子是:

dependentList :: forall n. (KnownNat n) => [Nat]
dependentList = [0..natVal (Proxy @n)]
Run Code Online (Sandbox Code Playgroud)

所以有趣的是,没有'单一'可缓存值dependentList; 但是一旦应用了一种类型,它就减少到一个常数,所以理论上一旦类型检查器运行,GHC就会认识到几个点都依赖于"相同" dependentList; 例如(使用TypeApplications)

main = do
  print (dependentList @5)
  print (dependentList @10)
  print (dependentList @5)
Run Code Online (Sandbox Code Playgroud)

我的问题是,GHC会认识到它可以共享这两个5列表吗?或者它是分别计算每一个?从技术上讲,甚至可以在编译时而不是运行时计算这些值,是否有可能让GHC这样做?

我的情况稍微复杂一些,但是应该遵循与示例相同的约束,但是我的类似dependentList值是计算密集的.

如果能让事情成为可能,我完全不反对使用类型类来做这件事; GHC缓存并重用类型词典吗?也许我可以把它变成类型类词典中的常量来获取缓存?

想法有人吗?或者有人读过我看看这是如何工作的?

我更喜欢这样做,编译器可以解决它而不是使用手动memoization,但我愿意接受:)

谢谢你的时间!

optimization performance caching haskell ghc

8
推荐指数
1
解决办法
123
查看次数

功能组成表示法

对于简单的函数组合,是否有"do notation"语法糖?

(即(.) :: (b -> c) -> (a -> b) -> a -> c)

我希望能够存储一些成分的结果供以后使用(同时仍然继续链.

如果可能的话,我宁愿不使用RebindableSyntax扩展.

我正在寻找这样的东西:

composed :: [String] -> [String]
composed = do
    fmap (++ "!!!")
    maxLength <- maximum . fmap length
    filter ((== maxLength) . length)

composed ["alice", "bob", "david"]
-- outputs: ["alice!!!", "david!!!"]
Run Code Online (Sandbox Code Playgroud)

我不确定这样的事情是否可能,因为早期函数的结果基本上必须通过"通过"maxLength的绑定,但我愿意听到任何其他类似的表达选项.基本上我需要收集信息,因为我通过合成以便以后使用它.

也许我可以用状态monad做这样的事情?

谢谢你的帮助!

编辑

这种事情有点起作用:

split :: (a -> b) -> (b -> a -> c) -> a -> c
split ab bac a = bac (ab a) a

composed …
Run Code Online (Sandbox Code Playgroud)

haskell composition do-notation

7
推荐指数
2
解决办法
307
查看次数

在已经是Functor的数据类型上使用`Fix`的递归方案?

仍在我的文本编辑器Rasa上工作

目前,我正在构建用于跟踪视口/拆分的系统(类似于vim拆分)。对我来说,将这种结构表示为一棵树似乎很自然:

data Dir = Hor
         | Vert
         deriving (Show)

data Window a =
  Split Dir SplitInfo (Window a) (Window a)
    | Single ViewInfo a
    deriving (Show, Functor, Traversable, Foldable)
Run Code Online (Sandbox Code Playgroud)

效果很好,我将Views 存储在树中,然后可以在它们上遍历/ fmap来更改它们,这也与镜头包很好地吻合!

我最近一直在学习递归方案,这似乎是一个合适的用例,因为树是递归的数据结构。

我设法弄清楚了,以构建Fixpoint版本:

data WindowF a r =
  Split Dir SplitInfo r r
    | Single ViewInfo a
    deriving (Show, Functor)

type Window a = Fix (WindowF a)
Run Code Online (Sandbox Code Playgroud)

但是,现在Functor实例已被r; 用尽。

我尝试了几种

deriving instance Functor Window
Run Code Online (Sandbox Code Playgroud)

但是它很令人吃惊,因为window是类型的同义词。

和:

newtype Window a = …
Run Code Online (Sandbox Code Playgroud)

haskell functor recursive-datastructures recursion-schemes fixpoint-combinators

5
推荐指数
1
解决办法
384
查看次数

镜头超过共群或可代表

这是这个问题的一个更具体的变体:Mutate only focus of Store Comonad?,以免一次问多个问题。

是否有任何与Control.Lens兼容的镜头允许我与 comonad 的焦点(来自 的值extract)或 Store Comonad ( pos)的索引/值进行交互?

似乎镜头在这里可能有用,但我一直找不到适合的东西;任何帮助将不胜感激,谢谢!

haskell comonad haskell-lens representable

5
推荐指数
1
解决办法
278
查看次数

使用 Comonad Fix 组合器

所以我最近一直在尝试固定点,并最终通过常规固定点的努力发现了一些用途;现在我正在转向共生不动点,我担心我已经陷入困境了;

以下是我尝试过的以及有效/无效的一些示例:

{-# language DeriveFunctor #-}
{-# language FlexibleInstances #-}
module WFix where

import Control.Comonad
import Control.Comonad.Cofree
import Control.Monad.Fix
Run Code Online (Sandbox Code Playgroud)

所以我从勒布定理开始列出;列表中的每个元素都是一个函数,它使用最终结果来计算其答案;这让我可以进行“电子表格”计算,其中值可以依赖于其他值。

spreadSheetFix :: [Int]
spreadSheetFix = fix $ \result -> [length result, (result !! 0) * 10, (result !! 1) + 1, sum (take 3 result)]
Run Code Online (Sandbox Code Playgroud)

好的,我已经完成了基本的修复工作,是时候继续讨论 comonad 类型了!以下是一些简单的 comonad 示例:

  data Stream a = S a (Stream a)
    deriving (Eq, Show, Functor)

  next :: Stream a -> Stream a
  next (S _ s) = s

  instance Comonad Stream where
    extract …
Run Code Online (Sandbox Code Playgroud)

haskell comonad fixpoint-combinators

3
推荐指数
1
解决办法
350
查看次数

通过动态功能列表管理数据

因此,我经常发现自己设计的"管道"就像数据流一样,并且通常最终导致管道本身是动态的.

有没有一种简单的方法可以做这样的事情?

pipe :: [a -> a] -> a -> a
Run Code Online (Sandbox Code Playgroud)

或者是否有一种不同的模式我应该用这样的东西来达成?它类似于State monad,但我不想编辑函数(a -> (), a)或其他:/

我意识到这是一个幺半群,所以我写了这个,这似乎是一个优雅的解决方案,它存在于某个库的某个库中吗?似乎大多数箭头和函数Monoids做不同的事情.

newtype Comp a = Comp { 
      runComp :: a -> a 
}

instance Monoid (Comp a) where
  (Comp a) `mappend` (Comp b) =  Comp (b . a)
  mempty = Comp id

pipe :: [a -> a] -> a -> a
pipe = runComp . foldMap Comp
Run Code Online (Sandbox Code Playgroud)

任何人都有他们用于此类事情的模式吗?谢谢!

haskell composition monoids

2
推荐指数
1
解决办法
126
查看次数

使用功能组合的fmap的惯用法

我对Haskell很新,但我很喜欢学习它,它与我以前用过的所有东西都有所不同.我在Monads上读了一两本书以及它们如何影响流量,但是我仍然有点麻烦.为了更好,我正在努力解决代码问题的优秀问题,现在我遇到问题2,我已经在下面发布了我的代码,它运行正常,但感觉不尽如人意.

具体来说,我想知道如何清理这个:

main = getContents >>= (return . sum . (fmap getSquareFootage) . lines) >>= print

我不喜欢混合函数组合和fmap AND这样>>=的行,我觉得很难读.是否有更惯用的方法来实现相同的结果?我也对任何和所有Haskell风格的建议持开放态度,我真的没有人可以谈论这个,谢谢!

TLDR; 我怎么能惯用地组合fmap,.>>=

import Data.List.Split (splitOn)

main :: IO ()
main = getContents >>= (return . sum . (fmap getSquareFootage) . lines) >>= print

getSquareFootage :: String -> Int
getSquareFootage box = area dims + slack dims
    where dims =  read <$> splitOn "x" box
        slack = minimum . sides
        sides [l, w, h] = …
Run Code Online (Sandbox Code Playgroud)

haskell

0
推荐指数
1
解决办法
95
查看次数