在阅读Bartosz 为程序员提供的优秀类别理论时,我陷入了第二个练习,即第二个练习,它处理了网络中的产品.鉴于一个poset,
b e
? ? ?
a ? c f ? h
? ? ?
d g
Run Code Online (Sandbox Code Playgroud)
如何在分类意义上定义产品?什么是两个对象的产品分类?那副产品呢?
如果我有一个解析器a : Parser A和一个解析器,b : Parser B那么我可以将它组合成一个解析器a | b : Parser (Either A B).当你开始添加更多替代品并获得类似的类型时,这会有点麻烦Either A (Either B C).我可以想象将之前的类型扁平化为类似的东西Alternative A B C.是否有我可以执行的标准转换,或者我坚持为类型生成一大堆样板文件Alternative A B C ....
将F#中缀运算符放在括号中,它的行为类似于函数,
let foo = (*) 3 2 // foo = 6
let factorial n = [2..n] |> List.fold (*) 1 // n!
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于:: operator(cons运算符),
let ls = (::) 1 [2..5] // Error: Unexpected symbol '::' in binding.
Run Code Online (Sandbox Code Playgroud)
这是什么原因?
Haskell的表现力使我们能够轻松定义一个powerset函数:
import Control.Monad (filterM)
powerset :: [a] -> [[a]]
powerset = filterM (const [True, False])
Run Code Online (Sandbox Code Playgroud)
为了能够执行我的任务,所述powerset按特定函数排序是至关重要的,所以我的实现类似于:
import Data.List (sortBy)
import Data.Ord (comparing)
powersetBy :: Ord b => ([a] -> b) -> [a] -> [[a]]
powersetBy f = sortBy (comparing f) . powerset
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,是否有一种方法只能在给定特定点和点的情况下生成powerset 的子集,其中和.例如,我的参数是一个整数列表(),它们按总和排序.现在我想提取只能在给定范围内的子集,可以说对.实现这一目标的一种方法是使powerset仅包括我的范围,但在处理更大的子集时这似乎(并且)无效:startendf(start) < f(end)|start| < |end|[1,2,3,4,5]37filter
badFunction :: Ord b => b -> b -> ([a] -> b) -> [a] -> [[a]]
badFunction start end f = filter …Run Code Online (Sandbox Code Playgroud) 给定具有固定点的任意数据结构,我们可以构造一个幺半代数而无需手动指定所有情况吗?
假设我们得到如下数据类型Expr.使用recursion-schemes图书馆,我们可以得出一个基地函子ExprF,可自动也有Functor,Foldable和Traversable实例.
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Semigroup (Sum(..))
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Prelude hiding (fail)
data Expr = Var String
| Const Int
| Add [Expr]
| Mult [Expr]
deriving Show
$(makeBaseFunctor ''Expr)
expr :: Fix ExprF
expr = ana project $ Add [Const 1, Const 2, Mult [Const 3, Const 4], Var "hello"]
Run Code Online (Sandbox Code Playgroud)
现在,假设我们想要计算叶子的数量expr …
获取数字数字的最有效方法是什么?
让我们从一个例子开始:
想象一下Fibonacci序列.现在让我们说我们想要知道哪个Fibonacci数是第一个有1000个数字(以10为基数表示).最多308位数(1476th Fibonacci数)我们可以通过使用轻松完成此操作logBase 10 <number>.如果该数字大于第1476个Fibonacci数,logBase则返回Infinity并且计算将失败.问题是308距离1000有点远,这是我们最初的目标.
一种可能的解决方案是将我们想要知道的数字转换为字符串的数字,并使用它的长度来确定数字计数.这对我的目的来说效率有点低,因为用10000来尝试这个时间需要花费很多时间.
其他问题中显示的最有效的方法是硬编码我真正不想做的所有可能的情况,特别是因为所提出的解决方案中所需的位数超过10.
那么回到我的问题:确定基数为10的数字计数的最佳(最有效)方法是什么?是真的将它转换为字符串并使用它的长度还是有任何"黑客"技巧,如0x5f3759df?
注意:我很欣赏任何语言的解决方案,即使它被标记为"haskell".
在Functor类类型定义中:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
为什么没有fmap默认实现?像这样的东西:
class Functor f where
fmap :: (a -> b) -> f a -> f b
fmap fn (f a) = (f $ (fn) a)
Run Code Online (Sandbox Code Playgroud)
当我编写实例时Functor,我手动为每个实例编写相同的代码.有没有办法指定默认实现?
我目前正在尝试解决20个中级Haskell练习练习,而且我试图在没有使用的情况下尝试实现mapM(moppy在练习中)sequence.
我只能[m b]通过简单的应用来制作,fmap但我不知道如何继续:
moppy :: [a] -> (a -> m b) -> m [b]
moppy la f = furry' f la -- how do I transform [m b] to m [b] without sequence
Run Code Online (Sandbox Code Playgroud)
有人能给我一个提示,看哪个方向?